object.ReferenceEquals或==运算符?

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.

  • @Grozz:是的,那家伙认为就像我一样;) (7认同)

Luk*_*keH 5

==运营商在编译时得到解决,不运行时,由于T是通用的编译器将使用的实施==提供object本身,检查引用相等.

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