'this'关键字是否可以等于null?

何塞·D。

在一个示例中,我的教授实现了Equals,如下所示:

public class Person {
    private string dni;

    // ...

    public override bool Equals(object o) {
        if (o == null)
            return (this == null);
        else {
            return ((o is Person) && (this.dni == (o as Person).dni));
        }
    }
}

我没有C#的经验,但是据我所知this在成员函数中不能为null(至少在C ++和Java(我所知道的语言)中是正确的),因此if似乎对我来说很奇怪。

我是对的还是我不知道c#中的任何组件使测试变得this == null必要?

埃里克·利珀特(Eric Lippert)

我没有使用C#的经验,但是据我所知,在成员函数中这不能为null(至少在C ++和Java(我知道的语言)中是正确的)

首先,请注意您的陈述是错误的。

在C ++中,在空接收器上调度方法是未定义的行为,并且未定义的行为意味着任何事情都可能发生。“任何东西”包括程序传递NULLthis和持续的,好像没有什么是错的。当然,this在C ++中检查是否为null有点愚蠢,因为只有在您不知道程序在做什么的情况下检查才为true ,因为它的行为是不确定的。

this在Java中是否可以为null我不知道。

现在来解决您有关C#的问题。假设==没有重载。稍后我们将回到这一点。

您的方法是用C#编写的。假设使用空接收器从C#程序调用它。C#编译器评估接收方是否可能为null。如果它可能为null,则确保它在调用该方法之前生成对代码进行空检查的代码。因此,在这种情况下,此检查毫无意义。当然,这是99.9999%的可能性。

假设它是通过反射调用的,就像Mike Z的回答一样。在这种情况下,不是C#语言执行调用;而是使用C#语言执行调用。相反,有人故意滥用反射。

假设它是从另一种语言调用的。我们有一个虚拟的方法;如果通过虚拟调度从另一种语言调用它,则必须执行空检查,因为否则我们怎么知道虚拟插槽中的内容呢?在这种情况下,它不能为null。

但是,假设它是使用非虚拟调度从另一种语言调用的。在这种情况下,另一种语言无需实现检查空值的C#功能。它可以调用它并传递null。

因此,在C#中this可以采用几种方法null,但是它们都远远超出了主流。因此,人们很少像您的教授那样编写代码。C#程序员习惯上认为this不是,null并且从不检查它。

现在我们已经解决了这个问题,让我们再来批评一下该代码。

public override bool Equals(object o) {
    if (o == null)
        return (this == null);
    else {
        return ((o is Person) && (this.dni == (o as Person).dni));
    }
}

首先,有一个明显的错误。我们假设它this可以为null,好吧,让我们开始吧。什么会this.dni引发空引用异常???如果您要假设它this可以为null,那么至少要始终这样做!(在Coverity,我们将这种情况称为“前向空缺”。)

下一步:我们先重写Equals然后再使用==内部,大概是指引用相等。这就是疯狂!现在,我们遇到的情况x.Equals(y)可能是正确的,但x==y可能是错误的!这太可怕了。请不要去那里。如果要覆盖,Equals则同时重载==,并在执行IEquatable<T>实现

(现在,有一个合理的论点是,疯狂在任何一个方向上都存在;如果与值语义==一致,Equalspersonx == persony可以不同于(object)personx == (object)persony,这似乎也很奇怪。这里的要点是,在C#中,相等性被弄得一团糟。)

而且:如果==以后重写该怎么办?现在,当代码的作者明确希望进行参考比较时,将Equals调用重写的==运算符。这是错误的秘诀。

我的建议是(1)写一个做正确的事情的静态方法,(2)ReferenceEquals每次可能会混淆什么是相等的含义时使用:

private static bool Equals(Person x, Person y)
{
    if (ReferenceEquals(x, y))
        return true;
    else if (ReferenceEquals(x, null))
        return false;
    else if (ReferenceEquals(y, null))
        return false;
    else 
        return x.dni == y.dni;
}

很好地涵盖了所有情况。请注意,当使用引用相等语义时,对于读者来说是非常清楚的另请注意,此代码使调试每种可能性都非常容易,可以在每种可能性上设置断点。最后,请注意,我们尽早采用了最便宜的产品。如果对象的引用相等,那么我们就不必对字段进行潜在的昂贵比较!

现在,其他方法很简单:

public static bool operator ==(Person x, Person y) 
{
  return Equals(x, y);
}
public static bool operator !=(Person x, Person y) 
{
  return !Equals(x, y);
}
public override bool Equals(object y)
{
  return Equals(this, y as Person);
}
public bool Equals(Person y)
{
  return Equals(this, y);
}

请注意,我的方式比您教授的方式更加优雅和清晰。并请注意,我的方法this无需this直接与null进行比较就可以处理null。

还是那句话:这一切说明,妥协的位置到达,其中价值和参考平等是可能的,有四个(==!=object.Equals(object)IEquatable<T>.Equals(T))的方式来实现平等,很复杂,没有假设,甚至混淆this可以或不可以是null

如果您对此主题感兴趣,我将在本周的博客中描述一个稍微棘手的问题:如何实现一般的比较,包括不平等。

http://ericlippert.com/2013/10/07/math-from-scratch-part-six-comparisons/

作为对C#如何处理平等的批评,这些注释特别有趣。

最后:别忘了重写GetHashCode确保您做对了。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

'this'关键字是否可以等于null?

来自分类Dev

是否可以通过.THIS关键字指向匿名类?

来自分类Dev

是否可以在vim modeline中添加关键字

来自分类Dev

golang`range`关键字是否可以输入类型信息?

来自分类Dev

是否可以在C ++中强制使用“ this”关键字?

来自分类Dev

是否可以制作自己的python关键字?

来自分类Dev

Solr返回的文档中是否可以获取关键字

来自分类Dev

是否可以通过.THIS关键字指向匿名类?

来自分类Dev

是否可以在if内联使用`retry`关键字?

来自分类Dev

是否可以通过 API 更新关键字的文本

来自分类Dev

#undef'ing关键字是否非法?

来自分类Dev

检查__thread关键字是否可用

来自分类Dev

使用“ this”关键字是否多余?爪哇

来自分类Dev

#undef'ing关键字是否非法?

来自分类Dev

Java是否有关键字“ that”

来自分类Dev

pythons关键字“in”是否检查“is”或“==”

来自分类Dev

将变量设置为等于找到关键字的行

来自分类Dev

是否有任何软件包可以存储一组Java关键字

来自分类Dev

是否可以将$ ref与JSON Schema中的其他关键字结合使用?

来自分类Dev

是否可以在不使用“ new”关键字的情况下使用Javascript原型?

来自分类Dev

是否可以忽略sqlalchemy映射类构造函数中的其他关键字?

来自分类Dev

是否可以使用Elasticsearch聚合将结果按关键字分组?

来自分类Dev

前向类声明是否可以在使用位置与class关键字互换?

来自分类Dev

是否可以在不使用New关键字的情况下执行方法隐藏?

来自分类Dev

如果我在try块内不使用throw关键字,是否可以引发异常?

来自分类Dev

SSRS:是否可以将参数值传递给SQL查询中的“ Values”关键字?

来自分类Dev

c#是否可以为字符串关键字创建扩展方法

来自分类Dev

是否可以将实例变量作为方法关键字的默认值传递?

来自分类Dev

是否有R函数可以在某个“单词距离”内查找关键字?

Related 相关文章

  1. 1

    'this'关键字是否可以等于null?

  2. 2

    是否可以通过.THIS关键字指向匿名类?

  3. 3

    是否可以在vim modeline中添加关键字

  4. 4

    golang`range`关键字是否可以输入类型信息?

  5. 5

    是否可以在C ++中强制使用“ this”关键字?

  6. 6

    是否可以制作自己的python关键字?

  7. 7

    Solr返回的文档中是否可以获取关键字

  8. 8

    是否可以通过.THIS关键字指向匿名类?

  9. 9

    是否可以在if内联使用`retry`关键字?

  10. 10

    是否可以通过 API 更新关键字的文本

  11. 11

    #undef'ing关键字是否非法?

  12. 12

    检查__thread关键字是否可用

  13. 13

    使用“ this”关键字是否多余?爪哇

  14. 14

    #undef'ing关键字是否非法?

  15. 15

    Java是否有关键字“ that”

  16. 16

    pythons关键字“in”是否检查“is”或“==”

  17. 17

    将变量设置为等于找到关键字的行

  18. 18

    是否有任何软件包可以存储一组Java关键字

  19. 19

    是否可以将$ ref与JSON Schema中的其他关键字结合使用?

  20. 20

    是否可以在不使用“ new”关键字的情况下使用Javascript原型?

  21. 21

    是否可以忽略sqlalchemy映射类构造函数中的其他关键字?

  22. 22

    是否可以使用Elasticsearch聚合将结果按关键字分组?

  23. 23

    前向类声明是否可以在使用位置与class关键字互换?

  24. 24

    是否可以在不使用New关键字的情况下执行方法隐藏?

  25. 25

    如果我在try块内不使用throw关键字,是否可以引发异常?

  26. 26

    SSRS:是否可以将参数值传递给SQL查询中的“ Values”关键字?

  27. 27

    c#是否可以为字符串关键字创建扩展方法

  28. 28

    是否可以将实例变量作为方法关键字的默认值传递?

  29. 29

    是否有R函数可以在某个“单词距离”内查找关键字?

热门标签

归档