[英]object.ReferenceEquals or == operator?
为什么ThrowIfNull
实现为:
static void ThrowIfNull<T>(this T argument, string name) where T : class
{
if (argument == null)
{
throw new ArgumentNullException(name);
}
}
不会更好地重写为:
static void ThrowIfNull<T>(this T argument, string name) where T : class
{
if (object.ReferenceEquals(argument, null))
{
throw new ArgumentNullException(name);
}
}
优点:它有助于避免混淆Equals
重载,并可能使代码更清晰。
对此有何不妥? 应该有一些。
两者之间没有区别。 您在使用重载 ==
会混淆覆盖 Equals
(在任一实现中都没有调用)(由于在编译时执行了重载,并且编译器对T
的使用不够了,因此在任何一个片段中都不相关任何特定的超载)。
只是为了表明我的意思:
static void ThrowIfFoo<T>(this T argument, string name) where T : class
{
if (argument == "foo")
{
throw new Exception("You passed in foo!");
}
}
测试:
"foo".ThrowIfFoo(); // Throws
string x = "f";
x += "oo"; // Ensure it's actually a different reference
x.ThrowIfFoo(); // Doesn't throw
ThrowIfFoo
不知道T
将是一个字符串 - 因为这取决于调用代码 - 并且只有在编译ThrowIfFoo
时才执行重载ThrowIfFoo
。 因此它使用operator ==(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
在最后一行中,编译器知道它可以使用==的重载,因为两个操作数都具有编译时类型的string
。
==
运算符在编译时解析,而不是运行时,并且由于T
是通用的,编译器将使用object
本身提供的==
的实现,它检查引用相等性。
这正是object.ReferenceEquals
所做的:调用object
提供的==
实现。
这主要是化妆品。
obj == null
将执行引用检查并返回,因此如果参数为null并且它不在T
重写,则将为Equals
。 当一个参数为null时,它需要一个非常不稳定/恶意的实现来返回true。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.