gpt4 book ai didi

c# - Equals(item, null) 或 item == null

转载 作者:IT王子 更新时间:2023-10-29 03:58:27 25 4
gpt4 key购买 nike

是使用 static Object.Equals 的代码检查空值比使用 == 运算符或 regular Object.Equals 的代码更健壮?后两者不是很容易被覆盖,以至于检查 null 不能按预期工作(例如,当比较值为 null 时返回 false)?

换句话说,是这样的:

if (Equals(item, null)) { /* Do Something */ }

比这更强大:
if (item == null) { /* Do Something */ }

我个人觉得后一种语法更容易阅读。在编写处理作者控制之外的对象(例如库)的代码时是否应该避免?是否应该始终避免(检查空值时)?这只是头发 split 吗?

最佳答案

这个问题没有简单的答案。 在我看来,任何说总是使用一个或另一个的人都给了你糟糕的建议。

实际上,您可以调用几种不同的方法来比较对象实例。给定两个对象实例 ab ,你可以写:

  • Object.Equals(a,b)
  • Object.ReferenceEquals(a,b)
  • a.Equals(b)
  • a == b

  • 这些都可以做不同的事情!

    Object.Equals(a,b) 将(默认情况下)对引用类型执行引用相等比较和对值类型执行按位比较。从 MSDN 文档:

    The default implementation of Equals supports reference equality for reference types, and bitwise equality for value types. Reference equality means the object references that are compared refer to the same object. Bitwise equality means the objects that are compared have the same binary representation.

    Note that a derived type might override the Equals method to implement value equality. Value equality means the compared objects have the same value but different binary representations.



    注意上面的最后一段……我们稍后会讨论这个。

    Object.ReferenceEquals(a,b) 仅执行引用相等比较。如果传递的类型是装箱值类型,则结果总是 false .

    a.Equals(b) 调用 Object的虚拟实例方法,其中 a 的类型可以覆盖做任何它想做的事情。调用是使用虚拟调度执行的,因此运行的代码取决于 a 的运行时类型.

    a == b 调用 a 的 **compile-time type* 的静态重载运算符.如果该运算符的实现调用 a 上的实例方法或 b ,它也可能取决于参数的运行时类型。由于分派(dispatch)基于表达式中的类型,因此以下可能会产生不同的结果:
    Frog aFrog = new Frog();
    Frog bFrog = new Frog();
    Animal aAnimal = aFrog;
    Animal bAnimal = bFrog;
    // not necessarily equal...
    bool areEqualFrogs = aFrog == bFrog;
    bool areEqualAnimals = aAnimal = bAnimal;

    所以,是的,使用 operator == 检查空值存在漏洞. 在实践中,大多数类型 不要过载 == - 但永远没有保证。

    实例方法 Equals()这里没有更好的。虽然默认实现执行引用/按位相等性检查,但类型可能会覆盖 Equals()成员方法,在这种情况下将调用此实现。用户提供的实现可以返回它想要的任何东西,即使与 null 相比也是如此。

    但是 Object.Equals() 的静态版本呢?你问?这最终可以运行用户代码吗?好吧,事实证明答案是肯定的。 Object.Equals(a,b)的实现扩展到以下方面:
    ((object)a == (object)b) || (a != null && b != null && a.Equals(b))

    你可以自己试试这个:
    class Foo {
    public override bool Equals(object obj) { return true; } }

    var a = new Foo();
    var b = new Foo();
    Console.WriteLine( Object.Equals(a,b) ); // outputs "True!"

    因此,以下语句是可能的: Object.Equals(a,b)当调用中的任何一种类型都不是 null 时运行用户代码.请注意 Object.Equals(a,b) 调用 Equals()的实例版本当任一参数为空时。

    简而言之,您获得的比较行为类型可能会有很大差异,具体取决于您选择调用的方法。然而,这里有一条评论:微软没有正式记录 Object.Equals(a,b) 的内部行为。 . 如果您需要在不运行任何其他代码的情况下将引用与 null 进行比较的铁定保证,您需要 Object.ReferenceEquals() :
    Object.ReferenceEquals(item, null);

    这种方法使意图非常明确 - 您特别期望结果是两个引用的比较以实现引用相等。使用类似 Object.Equals(a,null) 的好处在这里, 是不是不太可能有人稍后过来说:

    “嘿,这很尴尬,让我们将其替换为: a.Equals(null)a == null
    这可能会有所不同。

    然而,让我们在这里注入(inject)一些实用主义。 到目前为止,我们已经讨论了不同的比较方式产生不同结果的可能性。虽然情况确实如此,但在某些类型中可以安全地写入 a == null .内置 .NET 类,如 StringNullable<T>有明确定义的语义进行比较。此外,它们是 sealed - 防止通过继承改变他们的行为。以下是很常见的(并且是正确的):
    string s = ...
    if( s == null ) { ... }

    没有必要(而且丑陋)写:
    if( ReferenceEquals(s,null) ) { ... }

    所以在某些有限的情况下,使用 ==是安全和适当的。

    关于c# - Equals(item, null) 或 item == null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3507383/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com