object.ReferenceEquals或==运算符?

时间:2011-08-19 09:28:37

标签: c# linq equals throw

为什么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重载,并可能使代码更清晰。

对此有何不妥?应该有一些。

3 个答案:

答案 0 :(得分: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!");
    }
}

测试:

"foo".ThrowIfFoo(); // Throws

string x = "f";
x += "oo"; // Ensure it's actually a different reference

x.ThrowIfFoo(); // Doesn't throw

ThrowIfFoo不知道T将是一个字符串 - 因为这取决于调用代码 - 并且重载解析仅在{em>时执行{编译{1}} 。因此,它使用的是运算符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

答案 1 :(得分:5)

==运算符在编译时解析,而不是运行时,并且由于T是通用的,编译器将使用==本身提供的object的实现,检查参考相等性。

这正是object.ReferenceEquals所做的:调用==提供的object实现。

答案 2 :(得分:1)

这主要是化妆品。

obj == null将执行引用检查并返回,如果参数为null且未在Equals中覆盖,T将会{{1}}。当一个参数为空时,它需要一个非常不稳定/恶意的实现来返回true。