Background
Let's say I have the following class:
public class MyValue<T>
{
public T Value { get; set; }
public static bool operator ==(MyValue<T> first, MyValue<T> second)
{
// if first and second are the same instance, they are equal
if (object.Equals(first, second))
{
return true;
}
// for each of the objects, get a value indicating whether either
// the object or its Value property is null
bool firstIsNull = object.Equals(first, null) ? true : first.Value == null;
bool secondIsNull = object.Equals(second, null) ? true : second.Value == null;
// if both are null, they are equal
if (firstIsNull && secondIsNull)
{
return true;
}
// Not both are null. If one is, they are not equal
if (firstIsNull || secondIsNull)
{
return false;
}
// Neither first nor second is null; compare their values
return first.Value.Equals(second.Value);
}
// more code implementing !=, Equals, GetHashCode, implicit conversions and so on
}
This class will be used as the type on properties in an object model. An object could look like so:
public class SomeClass
{
public SomeClass()
{
SomeValue = new MyValue<string>();
}
public MyValue<string> SomeValue { get; set; }
}
The idea with this is that the class simply represents the value of its Value
property. It has some more functionality that is stripped away since it's not relevant for the question (some validation and stuff). Since the class has no value in itself, we want it to be as little intrusive as possible when used. Implicit conversions allows for code like this:
SomeClass instance = new SomeClass();
instance.SomeValue = "my string";
...and the question:
The idea with overloading the == (and !=) operator is to have an instance of the object where Value
is null
to compare equal to null
(partly because we feel it makes sense, partly because of backwards compatibility issues in the object model):
MyValue<string> a = new MyValue<string>();
MyValue<string> b = null;
bool areTheyEqual = (a == b); // this will be true
This may of course seem a bit confusing, but given that MyClass
is simply a wrapper, that in most of the code will be rather invisible, does it make sense to you too, or is it something really bad that we will regret for reasons that we overlooked?