Click here to Skip to main content
15,881,881 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have created a simple datetime class of my own like this.


public class datetime
 {


     private readonly long value = -1;

     public datetime(long value)
     {
         this.value = value;
     }

     public static implicit operator datetime(long value)
     {
         return new datetime(value);
     }




     public static bool operator ==(datetime datetimeLeftSide, datetime datetimeRightSide)
     {

         if (datetimeLeftSide.GetValue() == datetimeRightSide.GetValue())
         {
             return (true);
         }
         else
         {
             return (false);
         }
     }



     public static bool operator !=(datetime datetimeLeftSide, datetime datetimeRightSide)
     {

         return !(datetimeLeftSide == datetimeRightSide);
     }


     public long GetValue()
     {
         return (this.value);
     }


     public static implicit operator long(datetime first)
     {
         return first.value;
     }

 }



When I declare an array of datetime class like this

mydatetime = new datetime[3];


When I try to compare with another datetime variable
datetime dt = 1000;


if (mydatetime[1] != dt)   //I get the null reference exception here
{
   //do something
}


I get the null reference excpetion error with the array of datetime because I did not initilized the mydatetime array.

However, is there any work around to avoid this null reference exception error when I forgot to initialize the array before comparing.

I am looking for some ways that the values are automatically filled when array of datetime is just declared with the size, just for convenience.

What I have tried:

I tried to add this empty constructor to the datetime class. However, I still get the null reference exception error when the array is not filled with any values.
public datetime()
  {
      this.value = -1;
  }
Posted
Updated 25-Nov-20 0:09am
v3

The error is thrown by your equality operator. You are calling a method on both operands, without testing whether they are null first. And since your type is a reference type, one or both sides could be null.

(You'll have the same problem with your implicit datetime to long conversion operator - the datetime parameter could be null, and you'll get a NullReferenceException.)

You could fix your operator:
C#
public static bool operator ==(datetime datetimeLeftSide, datetime datetimeRightSide)
{
    if (datetimeLeftSide is null) return datetimeRightSide is null;
    if (datetimeRightSide is null) return false;
    return datetimeLeftSide.GetValue() == datetimeRightSide.GetValue();
}
But you should really be providing the full set of equality methods:
C#
public class datetime : IEquatable<datetime>
{
    ...
    
    public override int GetHashCode()
    {
        return value.GetHashCode();
    }
    
    public override bool Equals(object obj)
    {
        return Equals(obj as datetime);
    }
    
    public bool Equals(datetime other)
    {
        if (other is null) return false;
        return other.value == this.value;
    }
    
    public static bool operator ==(datetime left, datetime right)
    {
        return Equals(left, right);
    }
    
    public static bool operator !=(datetime left, datetime right)
    {
        return !Equals(left, right);
    }
    
    ...
}

NB: If you want the values to be filled automatically, you would need to create a value type instead:
Structure types - C# reference | Microsoft Docs[^]

However, you would not be able to have a default value of -1 for the field.
C#
public readonly struct datetime : IEquatable<datetime>
{
    private readonly long value;
    
    public datetime(long value)
    {
        this.value = value;
    }
    
    public long GetValue()
    {
        return value;
    }
    
    public override int GetHashCode()
    {
        return value.GetHashCode();
    }
    
    public override bool Equals(object obj)
    {
        return obj is datetime other && Equals(other);
    }
    
    public bool Equals(datetime other)
    {
        return other.value == this.value;
    }
    
    public static bool operator ==(datetime left, datetime right)
    {
        return Equals(left, right);
    }
    
    public static bool operator !=(datetime left, datetime right)
    {
        return !Equals(left, right);
    }
    
    public static implicit operator datetime(long value)
    {
        return new datetime(value);
    }
    
    public static implicit operator long(datetime first)
    {
        return first.value;
    }
}
 
Share this answer
 
No, you can't - your code is explicitly declaring an array of three datetime class instances, but the array itself does not contain the actual instances: it contains three references to those instances instead.

What you could do is make your class a struct instead as that is a value type instead of a reference type ... but ... that also has implications: Using struct and class - what's that all about?[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900