Reputation: 8425
Why is ThrowIfNull
implemented as:
static void ThrowIfNull<T>(this T argument, string name) where T : class
{
if (argument == null)
{
throw new ArgumentNullException(name);
}
}
Wouldn't it be better rewritten as:
static void ThrowIfNull<T>(this T argument, string name) where T : class
{
if (object.ReferenceEquals(argument, null))
{
throw new ArgumentNullException(name);
}
}
Pros: it helps avoiding confusing Equals
overloads and probably makes the code more clear.
Any cons to that? There should be some.
Upvotes: 6
Views: 3476
Reputation: 1500065
There's no difference between the two. You're confusing overriding Equals
(which isn't called in either implementation) with overloading ==
(which won't be relevant in either snippet as overloading is performed at compile time, and the compiler doesn't know enough about T
to use any specific overload).
Just to show what I mean:
static void ThrowIfFoo<T>(this T argument, string name) where T : class
{
if (argument == "foo")
{
throw new Exception("You passed in foo!");
}
}
Testing with:
"foo".ThrowIfFoo(); // Throws
string x = "f";
x += "oo"; // Ensure it's actually a different reference
x.ThrowIfFoo(); // Doesn't throw
ThrowIfFoo
doesn't know that T
will be a string - because that depends on the calling code - and the overload resolution is only performed when ThrowIfFoo
is compiled. Therefore it's using the operator ==(object, object)
rather than ==(string, string)
.
In other words, it's like this:
object foo1 = "foo";
string tmp = "f";
object foo2 = tmp + "oo";
Console.WriteLine(foo1.Equals(foo2)); // Prints True
Console.WriteLine(foo1 == foo2); // Prints false
Console.WriteLine((string) foo1 == (string) foo2); // Prints True
In the last line, the compiler knows it can use the overload of == because both operands have compile-time types of string
.
Upvotes: 12
Reputation: 269328
The ==
operator is resolved at compile-time, not runtime, and since T
is generic the compiler will use the implementation of ==
provided by object
itself, which checks for reference equality.
This is exactly what object.ReferenceEquals
does too: calls the ==
implementation provided by object
.
Upvotes: 5
Reputation: 27085
This is a mostly cosmetics.
obj == null
will do a reference check and return, so will Equals
if the argument is null and it's not overriden in T
. It would require a pretty wonky/malicious implementation to return true when one argument is null.
Upvotes: 1