Jon Skeet said:
Theorically equals should be a symetrical operation (docs state among
others the following should be true for every implementation of
equals)
x.Equals(a null reference (Nothing)) returns false.
x.Equals(y) returns the same value as y.Equals(x).
Therefore it is not symetrical when y == null
A more practical example:
if hashtable.contains(name) and value is a boolean and value equals
true return true else return false could be written as:
return true.Equals(hashtable[name]);
but cannot be written as:
hastable[name].Equals(true);
You could also use object.Equals(true, hashtable[name]).
But the operator == will cause a compiler warning because object and
true are different types. You can cast true as object but not
hastable[name] to (bool) as you may recieve an invalid cast exception
if value is not typeof boolean.
These are comparing references, assuming o1 and o2 are declared as
object.
These will all use the potentially overridden version of Equals.
Because null isn't an object - it's a reference which is to no object.
I was thinking along the lines of the NullObject pattern where there
would be no such thing as no object. "null" should be static instance
such as:
static Object.Null = new NullObject();
Because Equals is just like every other method - calling it involves
dereferencing, which you can't do with null.
See above
It's not a problem - it's the way it's meant to be. You shouldn't be
trying to dereference null.
Okay its not a "problem" but theorically they should be symetrical and
IMHO I shouldn't need to worry about it. I think there is a better
solution. The technical difficulty however is that null can be
assigned to any type. However this didn't stop them from developing
transparent proxies so I don't see why the runtime couldn't generate
an appropriate vtable when one attempts to dereference null as they do
when a transparent proxy is cast to another interface, the generated
vtable would implement object methods and by default throw an
exception for user specific methods.
vtable for normal instance of Foo (created when constructed)
Equals = Object.Equals()
Bar = Foo.Bar()
...
vtable for null instances of Foo (generated when null cast to Foo):
this = Object.Null
Equals = Object.Equals()
Bar = Object.ThrowNullException()
Perhaps taking this further perhaps a special operator could be used
to define the null instance implementation if desired.
class Foo {
public void Bar () { ... }
static Foo _null = new NullFoo();
// special null operator
public static operator null() { return _null; }
class NullFoo { public void Bar() { ... } }
}
now the vtable for null instance could look like this:
this = Foo.Null
Equals = Object.Equals()
Bar = NullFoo.Bar()
...
For interfaces however things become less clear what null
implementation would you like to use? the solution to that would to
use the static method for the desired class.
IFoo f = Foo.Null; // use foo null implemetation - perhaps does
nothing
f = Object.Null; // throws exception when calling Bar
The default implementation of operator null if not explicitly defined
as above would then be public static operator null() { return
Object.Null; }
- Kurt