比较2个自定义对象 - C#
我需要在基类中编写一个通用方法,该方法接受2个对象作为参数并比较它们的相等性。比较2个自定义对象 - C#
例:
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()
方法将接受的DataTypeOne
2个实例或DataTypeTwo
2个实例。
我的猜测是我需要使用反射?如果可以更易读/简洁,我可以使用LINQ。
编辑: 我想在基类中实现此方法的原因是因为项目的限制。有大量的开发人员在派生类上工作。通过在基类中实现这一点,我想让他们少担心一件事。
(假设你想要的是两个对象是否相等的所有字段进行比较。)
通常情况下,你就懒得使用反射对于这一点,你只是拿自己的每个字段。 IEquatable<T>
接口是为此目的而存在的,您也可能想要覆盖有关类型的Object.Equals()
。例如:
public class DataTypeTwo : BaseData, IEquatable<DataTypeTwo>
{
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
,您基本实现了您试图用“主等号方法”方案实现的内容(在我看来)。也就是说,使用DataTypeTwo
的人将能够自然地测试平等,而不必知道任何关于您的API的特殊情况 - 他们只会像使用其他东西一样使用Equals
。
编辑:感谢贾里德提醒我关于GetHashCode
。您还需要覆盖它以通过确保任何两个“相等”的对象也返回相同的哈希码来保持哈希表中的正常行为。
你仍然需要覆盖GetHashCode – JaredPar 2009-04-28 14:06:35
为什么你需要GetHashCode,等于不足? – 2009-04-29 06:15:41
为了改变平等比较行为,请不要将类更改为结构体。微小的数据类型,如笛卡尔坐标,预计会以某种“按价值”的方式表现得很好;但是另一个程序员将会认为是一个类的数据结构不应该被作为结构来进行价值比较 - 你也将不可见地改变行为。初始化和(最重要的)分配。 – perfectionist 2013-09-02 09:53:39
是的,您将不得不使用反射,因为基类对派生类一无所知。但为什么你想在基类中实现该功能?为什么不在派生类中?
此外还有一个通过重写Object.GetHashCode()和Object.Equals()来完成此操作的标准方法。
我可能会做这样的事情:
public abstract class BaseData : IEquatable<BaseData>
{
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);
}
}
也许一个解释,为什么它是“疯狂”会很好。 – madcolor 2009-04-28 14:22:36
这就是我想出了使用反射。希望能帮助到你。
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;
}
不要这样做。继承是要走的路,每个类都应该在必要时重写Equal和GetHashCode。
也许你现在可以从这些开发者那里完成一些工作,但是在将来当产品需要维护时,我会回来咬你。
说真的,只是试图找到另一种方式来帮助。
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;
}
为什么不重写Object.Equals? – Paco 2009-04-28 14:05:54
为什么你需要在基类中实现AreEqual(以及为什么没有泛型)?如果AreEqual是抽象的,DataTypeOne和DataTypeTwo实现AreEqual,那么这是一个更清晰的解决方案。简而言之:常见的AreEqual方法的原因是什么? – boj 2009-04-28 14:07:52