Gro*_*ozz 6 c# linq equals throw
为什么ThrowIfNull实施为:
static void ThrowIfNull<T>(this T argument, string name) where T : class
{
if (argument == null)
{
throw new ArgumentNullException(name);
}
}
Run Code Online (Sandbox Code Playgroud)
不会更好地重写为:
static void ThrowIfNull<T>(this T argument, string name) where T : class
{
if (object.ReferenceEquals(argument, null))
{
throw new ArgumentNullException(name);
}
}
Run Code Online (Sandbox Code Playgroud)
优点:它有助于避免混淆Equals过载,并可能使代码更清晰.
对此有何不妥?应该有一些.
Jon*_*eet 12
两者之间没有区别.你是混淆覆盖 Equals(在任何一个实现中都没有调用)和重载 ==(由于在编译时执行重载,并且编译器不知道T使用任何特定的重载,因此在任何一个片段中都不相关) .
只是为了表明我的意思:
static void ThrowIfFoo<T>(this T argument, string name) where T : class
{
if (argument == "foo")
{
throw new Exception("You passed in foo!");
}
}
Run Code Online (Sandbox Code Playgroud)
测试:
"foo".ThrowIfFoo(); // Throws
string x = "f";
x += "oo"; // Ensure it's actually a different reference
x.ThrowIfFoo(); // Doesn't throw
Run Code Online (Sandbox Code Playgroud)
ThrowIfFoo不知道这T将是一个字符串 - 因为这取决于调用代码 - 并且重载解析仅在ThrowIfFoo编译时执行.因此它使用的是运算符==(object, object)而不是==(string, string).
换句话说,它是这样的:
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
Run Code Online (Sandbox Code Playgroud)
在最后一行中,编译器知道它可以使用==的重载,因为两个操作数都具有编译时类型string.
该==运营商在编译时得到解决,不运行时,由于T是通用的编译器将使用的实施==提供object本身,检查引用相等.
这正是object.ReferenceEquals它所做的:调用由==提供的实现object.