为什么这两个比较有不同的结果?

时间:2014-01-14 19:29:26

标签: c# .net equality

为什么此代码返回true:

new Byte() == new Byte()   // returns true

但此代码返回false:

new Byte[0] == new Byte[0] // returns false

4 个答案:

答案 0 :(得分:143)

因为new Byte()创建的值类型会按值进行比较(默认情况下,它会返回值为byte的{​​{1}})。 0创建数组,这是一个引用类型并通过引用进行比较(这两个数组实例将有不同的引用)。

有关详细信息,请参阅Value Types and Reference Types文章。

答案 1 :(得分:43)

.NET中的字节为value types,这意味着当且仅当两个字节具有相同值时,==运算符才返回true。这也称为value equality

但.NET中的数组是reference types,这意味着==运算符返回true,当且仅当它们引用内存中的同一数组实例时才会返回true。这也称为reference equality or identity

请注意,==运算符可以为引用和值类型重载。例如,System.String是引用类型,但字符串的==运算符按顺序比较数组中的每个字符。请参阅Guidelines for Overloading Equals() and Operator == (C# Programming Guide)

如果您想测试数组是否包含完全相同的值(按顺序),您应该考虑使用Enumerable.SequenceEqual而不是==

答案 2 :(得分:10)

比较引用实际上是比较指针地址,这是不同的,这是返回false的原因,而在值地址无关紧要,它比较值。

编译器尝试将值类型存储在寄存器中,但由于寄存器数量有限,堆栈中的进一步存储发生值为[Reference],而引用类型位于堆栈中,但值保存堆中的内存地址。

比较在这里比较堆栈中存在的值,在第一种情况下对于两者都是相同的,而在第二种情况下,它是不同的堆的地址。

  

reference

答案 3 :(得分:1)

==运算符有一个重载,其中两个操作数的类型为byte,并且它被实现为比较每个字节的值;在这种情况下,您有两个零字节,它们是相等的。

==运算符没有为数组重载,因此在第二种情况下使用了具有两个object操作数的重载(因为数组类型为object),并且它的实现比较两个对象的引用。对两个数组的引用是不同的。

值得注意的是,这与({1}}是值类型且数组是引用类型的事实没有任何关系。 byte的{​​{1}}运算符仅具有值语义 ,因为运算符具有该实现的特定重载。如果那个重载不存在那么 没有重载,其中两个字节将是有效的操作数,因此代码根本不会编译。通过创建自定义==并将其两个实例与byte运算符进行比较,您可以轻松地看到这一点。除非您为这些类型提供struct的实现,否则代码将无法编译。