3

当我必须为

public class SampleClass
{
    public int Prop { get; set; }
}

我应该做

null == new SampleClass() 

new SampleClass() == null

new SampleClass().Equals(null)

错误的?

还有呢

new SampleClass() != null

它也应该是假的吗?

更新人们质疑这个问题背后的原因。假设 != 和 == 总是相反的。但是,如果我实现这些方法以使上述所有比较结果为假,那么在某些情况下 == 和 != 运算符将产生相同的结果。所以 != 应该返回 true 还是 false 是一个两难的问题。

4

8 回答 8

7

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

编辑:因此通过扩展,new SampleClass() != null应该是true. null不像NaN; 它的定义非常明确。

于 2009-08-18T19:36:43.963 回答
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?
于 2009-08-18T19:40:35.890 回答
2

除了已说明的内容外,请注意:

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

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

所以....

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

阅读 .NET 框架设计者在这个问题上所说的话:

为什么可空关系运算符不返回“bool”?而不是“布尔”?

有关更多信息,请阅读:

于 2009-08-18T20:03:19.107 回答
1

我不确定我是否完全理解您的问题,但 null (根据定义)不是一个值。像这样,

null == new SampleClass()

真的没有任何意义(而且,真的,其他比较都没有)。

你能改写你的问题吗?

于 2009-08-18T19:37:24.680 回答
1

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

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

于 2009-08-18T19:41:18.980 回答
1

Null 永远不应与非 null 引用进行比较。通过扩展,您的 != 应该返回 true,因为它与等式相反。

于 2009-08-18T19:43:51.343 回答
0

如果您有一个对象的实例,则您没有 null 并且所有相等比较器都应该尊重这一点。

于 2009-08-18T19:41:22.847 回答
0

我认为这是一个特别有趣的问题。我对此的看法与任何答案都不完全相同,所以请忍受我这么晚才来。

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

例如在 SQL 中,我们可能有1 = nulland1 <> null都 return null,因为它的概念null更接近数学,其中 null 不等于任何东西,包括 null,但也不完全不等于任何东西。

如果需要,我们可以为此使用 C# null,但这并不是null.NET 中默认含义的工作方式。

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

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

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

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

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

  2. 对于给定的 x 和 y,x == y总是给出相反结果的语义不会消失。x != y

所以:

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

  2. 我们仍然必须x != null返回对面x == null

现在,自从 .NET 2.0 以来,我们已经有了一个可以做到这一点的内置函数:(Nullable<T>T?在 C# 语法中)。它还有一些额外的支持来帮助它在面对拳击时表现良好(这使得它在人的方式上表现得像一个引用类型,所以如果没有这些额外的支持,我们就会遇到复杂的情况,即x == null返回 true 但(object)x == null会返回 false。

情况也是如此,它Nullable<T>可以处理几乎任何我们想对 null 使用这种稍微不同的语义的情况,这意味着如果我们可能想要定义的话,真的没有任何情况了Equals()传递 null 时返回 true的方法。

于 2011-12-12T14:39:41.657 回答