object.ReferenceEquals 或 == 运算符?

发布于 2024-11-30 12:45:22 字数 603 浏览 1 评论 0原文

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

这样做有什么缺点吗?应该有一些。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时光暖心i 2024-12-07 12:45:22

两者没有区别。您将覆盖 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 时执行。因此,它使用运算符 ==(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编译时类型。

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.

不爱素颜 2024-12-07 12:45:22

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

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

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.

只有一腔孤勇 2024-12-07 12:45:22

这主要是化妆品。

obj == null 将执行引用检查并返回,如果参数为 null 并且未在 T 中覆盖,Equals 也会执行引用检查并返回。当一个参数为空时,它需要一种相当古怪/恶意的实现来返回 true。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文