为什么此代码返回true:
new Byte() == new Byte() // returns true
但是此代码返回false:
new Byte[0] == new Byte[0] // returns false
为什么此代码返回true:
new Byte() == new Byte() // returns true
但是此代码返回false:
new Byte[0] == new Byte[0] // returns false
Answers:
因为new Byte()
创建的是按值比较的值类型(默认情况下,它将返回byte
value 0
)。和new Byte[0]
创建一个数组,它是一个引用类型,并按引用进行比较(这两个数组实例将具有不同的引用)。
有关详细信息,请参见值类型和引用类型文章。
字节是.NET中的值类型,这意味着==
当且仅当两个字节具有相同的值时,运算符才返回true。这也称为价值平等。
但是数组是.NET中的引用类型,这意味着==
运算符仅当在内存中引用相同的数组实例时才返回true。这也称为引用相等或标识。
注意,==
引用类型和值类型都可以重载运算符。System.String
例如,是引用类型,但是==
字符串的运算符按顺序比较数组中的每个字符。请参见重载Equals()和运算符==的准则(C#编程指南)。
如果要测试数组是否包含完全相同的值(按顺序),则应考虑使用Enumerable.SequenceEqual
代替==
。
==
运营商及其双重性质。这个答案显然涵盖了这一点。
System.Array
该类不提供重载,因此它使用默认的引用相等性。您可能会认为可以创建自己的数组类型(System.Array
毕竟是抽象的),但是编译器不允许您从其继承。不过,您可能会巧妙地使用隐式运算符来将数组转换为另一种类型,这可能会相当接近,但是这个主意使我的皮肤难以捉摸。
比较引用实际上是比较指针地址,这是不同的,这就是返回false和在值地址中返回值的原因,无论它是否比较值。
编译器尝试将值类型存储在寄存器中,但由于寄存器数量有限,当引用类型在堆栈中但值保留堆中的内存地址时,值[Reference]将在堆栈中进一步存储。
这里的比较比较堆栈中存在的值,在第一种情况下两者都是相同的,而在第二种情况下则是堆的地址不同。
new Byte()
调用的结果很可能存储在寄存器中。
==
运算符有一个重载,其中两个操作数都是类型byte
,并且实现为比较每个字节的值。在这种情况下,您有两个零字节,它们相等。
在==
操作者不超载为阵列,以便具有两个过载object
时使用的操作数(因为数组是类型的object
)在第二种情况下,其实现比较两个对象的引用。对这两个数组的引用是不同的。
值得注意的是,这与(直接)与byte
值类型和数组为引用类型无关。==
for的运算符仅byte
具有值语义,因为该实现对该运算符有特定的重载。如果超载不存在那么就可以无过载为两个字节将是有效的操作数,这样的代码不会在所有的编译。通过创建一个自定义并将其两个实例与运算符进行比较,您可以轻松地看到它。除非您为这些类型提供自己的实现,否则代码不会编译。struct
==
==