C#中两个结构的平等

我寻找这个结构的两个实例之间的相等。

public struct Serie { T[] X; double[] Y; public Serie(T[] x, double[] y) { X = x; Y = y; } public override bool Equals(object obj) { return obj is Serie && this == (Serie)obj; } public static bool operator ==(Serie s1, Serie s2) { return s1.X == s2.X && s1.Y == s2.Y; } public static bool operator !=(Serie s1, Serie s2) { return !(s1 == s2); } 

这不起作用。 我错过了什么?

  double[] xa = { 2, 3 }; double[] ya = { 1, 2 }; double[] xb = { 2, 3 }; double[] yb = { 1, 2 }; Serie A = new Serie(xa, ya); Serie B = new Serie(xb, yb); Assert.AreEqual(A, B); 

您正在比较数组引用而不是它们的内容。 yayb指的是不同的数组。 如果要检查数组的内容,则必须明确地执行此操作。

我不认为框架中有任何内容可以帮助你做到这一点,我担心。 这样的东西应该工作:

 public static bool ArraysEqual(T[] first, T[] second) { if (first == second) { return true; } if (first == null || second == null) { return false; } if (first.Length != second.Length) { return false; } IEqualityComparer comparer = EqualityComparer.Default; for (int i = 0; i < first.Length; i++) { if (!comparer.Equals(first[i], second[i])) { return false; } } return true; } 

另外,您的结构有点可变,因为在创建结构后可以更改数组内容。 你真的需要这个结构吗?

编辑:正如尼克在评论中提到的那样,你也应该覆盖GetHashCode。 同样,您需要从数组中获取内容(同样,如果数组之后发生更改,这将导致问题)。 类似的实用方法:

 public static int GetHashCode(T[] array) { if (array == null) { return 0; } IEqualityComparer comparer = EqualityComparer.Default; int hash = 17; foreach (T item in array) { hash = hash * 31 + comparer.GetHashCode(item); } return hash; } 

我不认为框架中有任何内容可以帮助你做到这一点,我担心

在4.0中,有:

 StructuralComparisons.StructuralEqualityComparer.Equals(firstArray, secondArray); 

您应该在Equality逻辑中比较Array的内容……

此外,建议您在结构上实现IEquatable接口,因为这可以防止在某些情况下出现装箱/拆箱问题。 http://blogs.msdn.com/jaredpar/archive/2009/01/15/if-you-implement-iequatable-t-you-still-must-override-object-s-equals-and-gethashcode.aspx

部分s1.Y == s2.Y测试它们是否是对同一数组实例的 2个引用,而不是内容是否相等。 所以尽管有标题,这个问题实际上是关于数组(-reference)之间的相等性。

一些额外的建议:由于你正在重载,你应该将 Serie<> 设计为不可变的,因为嵌入式数组我会把它变成一个类而不是一个结构。

调用==在数组上执行引用相等 – 它们不比较元素的内容。 这基本上意味着a1 == a2只会返回true,如果完全相同的实例 – 这不是你想要的,我认为..

你需要修改你的operator ==来主持x数组的内容,而不是它的参考值。

如果您使用的是.NET 3.5(带链接),您可以执行以下操作:

 public static bool operator ==(Serie s1, Serie s2) { return ((s1.X == null && s2.X == null) || s1.X.SequenceEquals( s2.X )) && s1.Y == s2.Y; } 

如果需要进行深度比较(超出引用),可以为SequenceEquals提供T类型的自定义IEqualityComparer

您可能还应该考虑为您的struct实现IEquatable接口。 它将帮助您的代码更好地使用LINQ和执行对象比较的.NET框架的其他部分。

您可以为结构创建私有访问器并使用CollectionAssert

 [TestMethod()] public void SerieConstructorTest() { double[] xa = { 2, 3 }; double[] ya = { 1, 2 }; double[] xb = { 2, 3 }; double[] yb = { 1, 2 }; var A = new Serie_Accessor(xa, ya); var B = new Serie_Accessor(xb, yb); CollectionAssert.AreEqual(AX, BX); CollectionAssert.AreEqual(AY, BY); } 

这段代码工作正常。

参考文献:

  • CollectionAssert.AreEqual方法
  • 如何创建私有访问者