这让我把头发拉了几天:
byte[] _A = new byte[64];
// Fill _A with some meaningful, valid data.
byte[] _B = new byte[_A.Length];
_A.CopyTo( _B, 0 );
if( !_A.Equals( _B ) ) {
throw new WtfException(
"It appears object.Equals doesn't work on arrays of value types...");
}
是的,这会引发WtfException
。我花了几天时间才注意到。 byte
是ValueType
。但是,byte[]
是System.Array
,是引用类型。根据.NET文档:
Equals的默认实现支持引用相等 引用类型和值类型的按位相等。参考 等于意味着被比较的对象引用引用 同一个对象。按位相等意味着被比较的对象具有 相同的二进制表示。
有人可以帮忙吗?
答案 0 :(得分:5)
您正在比较引用类型(数组)而不是值类型。 _A和_B确实不同 - 它们是两个碰巧包含相同值的不同数组。
答案 1 :(得分:3)
_A和_B不是对同一数组的引用。因此,他们并不平等。你需要做这样的事情:
private static bool ValueTypeArraysAreEqual( Array p_lhs, Array p_rhs ) {
if( p_lhs == null ) {
return p_rhs == null;
}
if( p_rhs == null ) {
return false;
}
if( p_lhs.Length != p_rhs.Length ) {
return false;
}
return Parallel.For( 0, p_lhs.Length, ( _lcv, loopState ) => {
if( !p_lhs.GetValue( _lcv ).Equals( p_rhs.GetValue( _lcv ) ) ) {
loopState.Break();
}
} ).IsCompleted;
}
你可以在循环中使用object.Equal,因为你可以比较Loop包含的ValueTypes。 System.Threading.Tasks.Parallel的使用帮助我更快地移动事物。 Parallel.For返回一个结构,告诉您循环是否已停止。如果你从未用loopState.Break停止循环,那么它们都匹配。如果出于某种原因,你不能使用Parallel.For,只需执行一个返回false的for循环;
答案 2 :(得分:2)
数组使用引用相等,而不是成员相等。所以这表现得像预期的那样。
如果需要,可以使用SequenceEqual
进行成员相等。
答案 3 :(得分:2)
该文档准确地解释了您所看到的内容。可怕的类比警告:只是因为两张纸都写有相同的数字,不会使它们成为同一张纸。
您可能会对SequenceEqual
感兴趣,当且仅当两个序列包含相同顺序的相同值时,才会返回true
。