如何在平等比较中处理空值?

时间:2009-08-18 19:35:15

标签: c# .net operators iequatable equals-operator

当我必须为

实现相等比较器时
public class SampleClass
{
    public int Prop { get; set; }
}

我应该

null == new SampleClass() 

new SampleClass() == null

new SampleClass().Equals(null)

假?

那么

new SampleClass() != null

它也应该是假的吗?

更新人们质疑这个问题背后的原因。这应该是 !=和==永远是对立的。但是如果我实现这些方法所以所有这些比较都会导致错误,那么将会出现==和!=运算符会产生相同结果的情况。因此,是否应该返回true或false是一个两难的选择。

8 个答案:

答案 0 :(得分:7)

这甚至是个问题吗?不,null永远不应该等于一个对象。

修改:因此,new SampleClass() != null的扩展名应为truenullNaN不同;它的定义非常明确。

答案 1 :(得分:4)

你的例子中所有与null相等的比较肯定是假的。最后一个也很重要:

new SampleClass() != null

这一定必须评估为true,因为这是检查引用变量是否已初始化的常用方法。如果要评估false,它可能无意中在整个地方重新分配变量,因为C#开发人员期望来自运营商的某种行为。另一个例子:

SampleClass myVar = new SampleClass();

// Various stuff happening here, possibly setting myVar to null

if (myVar != null)
{
    // Programmer go "WTFBBQ?" when he finds this doesn't get executed
    myVar.DoStuff();
}

困惑,程序员将其更改为:

if (myVar == null)
{
    myVar = new SampleClass();
}

myVar.DoStuff(); // null reference exception, huh?

答案 2 :(得分:2)

除了陈述的内容外,请注意:

预定义的引用类型相等运算符是:

bool operator ==(object x, object y);
bool operator !=(object x, object y);

...所以

SampleClass a = null;
SampleClass b = null;
  • a == b是真的
  • a!= b是假的

阅读.NET框架设计人员在该问题上所说的内容:

Why don't nullable relational operators return “bool?” instead of “bool“?

有关详细信息,请阅读:

答案 3 :(得分:1)

我不确定我是否完全理解你的问题,但是null(根据定义)不是一个值。因此,

null == new SampleClass()

没有任何意义(并且,实际上,其他比较都没有)。

你能改一下你的问题吗?

答案 4 :(得分:1)

正如其他人所说,null永远不会等于包括null在内的任何其他东西。这是因为null不是值,而是缺少值。

对于您的具体问题,您似乎正在尝试实例化尚未初始化的对象,并且您想要确定该对象是否已初始化。我的建议是包含一个属性,指示对象是否已初始化。

答案 5 :(得分:1)

Null永远不应该等于非null引用。通过扩展,你的!=应该返回true,因为它与相等相反。

答案 6 :(得分:0)

如果你有一个对象的实例,你没有null,所有相等的比较器都应该尊重它。

答案 7 :(得分:0)

我认为这是一个特别有趣的问题。我对它的看法与任何答案都不完全相同,所以请耐心等待我的到来。

首先要注意的是,.NET中的null在某些其他上下文中与null并不完全相同,但它可用于对它们进行建模。

在SQL中,我们可能1 = null1 <> null都返回null,因为null的概念更接近数学,其中null不是等于任何东西,包括null,但也不等于任何东西。

如果需要,我们可以使用C#null,但这并不完全是.NET中null的默认含义。

对于任何引用类型,null具有特定的定义含义,可能还有上下文提供的其他含义。

具体含义是“没有这种类型的对象的实例”。

给定上下文中的附加含义可能是“整数值实际上是空的,而不是匹配任何整数”,或者“没有这样的项目集合,甚至不是空的”,或者“这是第一个这样的项目,所以没有早期的“等等,取决于我们如何使用它。 (另外,它可能意味着“哦,亲爱的,真的不应该是空的,最好抛出异常”)。

现在,我们可能希望大量使用这些附加含义,以至于我们定义了一个对象等于null有意义的情况,或者至少不等于null。但是,我们有以下限制:

  1. 对于引用类型的值,null的特定定义意味着没有该引用类型的实例不会消失。

  2. 对于给定的x和y,x == y始终会给x != y提供相反结果的语义不会消失。

  3. 因此:

    1. 如果我们想要一个实例可以等于null的类型,它必须是一个值类型。

    2. 我们仍然需要x != null返回x == null的反面。

    3. 现在,自从.NET 2.0以来,我们已经有了一个内置的功能:Nullable<T>(或C#语法中的T?)。它还有一些额外的支持,以帮助它在拳击面前表现良好(这使得它在人的方式表现得像一个参考类型,所以如果没有额外的支持我们会有并发症x == null将返回true但是(object)x == null会返回false。

      情况也是如此,Nullable<T>可以处理几乎任何我们想要使用这种稍微不同的语义为null的情况,这意味着没有任何案例可以留下来。我们可能想要定义一个Equals()方法,该方法在传递null时返回true。