比较2个自定义对象 – C#

我需要在基类中编写一个generics方法,它接受2个对象作为参数,并将它们进行相等性比较。

例如:

public abstract class BaseData { public bool AreEqual(object O1, object O2) { //Need to implement this } } public class DataTypeOne : BaseData { public string Name; public string Address; } public class DataTypeTwo : BaseData { public int CustId; public string CustName; } 

AreEqual()方法将接受2个DataTypeOne实例或2个DataTypeTwo实例。

我的猜测是我需要使用Reflection吗? 我可以使用LINQ,如果它更可读/简洁。

编辑:我想在基类中实现此方法的原因是因为项目限制。 有大量的开发人员在派生类上工作。 通过在基类中实现这一点,我试图减少一件事让他们担心。

(假设你想要的是比较两个对象的所有字段是否相等。)

通常,你不会为此使用reflection,你只需要自己比较每个字段。 IEquatable接口存在于此目的,您也可能希望覆盖有问题类型的Object.Equals() 。 例如:

 public class DataTypeTwo : BaseData, IEquatable { public int CustId; public string CustName; public override int GetHashCode() { return CustId ^ CustName.GetHashCode(); // or whatever } public override bool Equals(object other) { return this.Equals(other as DataTypeTwo); } public bool Equals(DataTypeTwo other) { return (other != null && other.CustId == this.CustId && other.CustName == this.CustName); } } 

另外,请考虑您的类型是否有意义作为struct 。 值类型通过逐个字段比较自动比较相等性。

请注意,通过重写Equals ,您基本上可以实现您尝试使用“master equals方法”方案实现的function(在我看来)。 也就是说,使用DataTypeTwo将能够自然地测试相等性而无需了解有关API的任何特殊内容 – 他们只会像使用其他东西一样使用Equals

编辑:感谢Jared提醒我有关GetHashCode 。 您还希望通过确保任何两个“相等”的对象也返回相同的哈希代码来覆盖它以维护哈希表中的正常外观行为。

这是我用reflection得出的结果。 希望能帮助到你。

 public bool AreEqual(object obj) { bool returnVal = true; if (this.GetType() == obj.GetType()) { FieldInfo[] fields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); foreach (FieldInfo field in fields) { if(field.GetValue(this) != field.GetValue(obj)) { returnVal = false; break; } } } else returnVal = false; return returnVal; } 

不要这样做。 inheritance是最好的方法,每个类都应该覆盖需要的Equal和GetHashCode。

也许你现在可以从这些开发人员那里完成一些工作,但是当我们需要维护产品时,我会回来咬你的屁股。

说真的,试着寻找另一种方法来帮助。

我可能会这样做:

 public abstract class BaseData : IEquatable { public abstract bool Equals(BaseData other); } public class DataTypeOne : BaseData { public string Name; public string Address; public override bool Equals(BaseData other) { var o = other as DataTypeOne; if(o == null) return false; return Name.Equals(o.Name) && Address.Equals(o.Address); } } public class DataTypeTwo : BaseData { public int CustId; public string CustName; public override bool Equals(BaseData other) { var o = other as DataTypeTwo; if (o == null) return false; return CustId == o.CustId && CustName.Equals(o.CustName); } } 

是的,您将不得不使用reflection,因为基类对派生类一无所知。 但是为什么要在基类中实现该函数? 为什么不在派生类中?

此外,还有一种标准方法可以通过重写Object.GetHashCode()和Object.Equals()来实现此目的。

 public void CompareTwoObjects() { try { byte[] btArray = ObjectToByteArray(object1); //object1 is you custom object1 byte[] btArray2 = ObjectToByteArray(object2); //object2 is you custom object2 bool result = ByteArrayCompare(btArray, btArray2); } catch (Exception ex) { throw ex; } } public byte[] ObjectToByteArray(object _Object) { try { // create new memory stream System.IO.MemoryStream _MemoryStream = new System.IO.MemoryStream(); // create new BinaryFormatter System.Runtime.Serialization.Formatters.Binary.BinaryFormatter _BinaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); // Serializes an object, or graph of connected objects, to the given stream. _BinaryFormatter.Serialize(_MemoryStream, _Object); // convert stream to byte array and return return _MemoryStream.ToArray(); } catch (Exception _Exception) { // Error Console.WriteLine("Exception caught in process: {0}", _Exception.ToString()); } // Error occured, return null return null; } public bool ByteArrayCompare(byte[] a1, byte[] a2) { if (a1.Length != a2.Length) return false; for (int i = 0; i < a1.Length; i++) if (a1[i] != a2[i]) return false; return true; }