比较 2 个自定义对象 - C#
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/798117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Comparing 2 custom objects - C#
提问by DotnetDude
I need to write a generic method in the base class that would accept 2 objects as parameters and compares them for equality.
我需要在基类中编写一个通用方法,该方法将接受 2 个对象作为参数并比较它们是否相等。
Ex:
前任:
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;
}
The AreEqual()
method would accept 2 instances of DataTypeOne
or 2 instances of DataTypeTwo
.
该AreEqual()
方法将接受 的 2 个实例DataTypeOne
或 的 2 个实例DataTypeTwo
。
My guess is I need to use Reflection? I can use LINQ if it can be more readable/concise.
我的猜测是我需要使用反射?如果可以更易读/简洁,我可以使用 LINQ。
EDIT: The reason I would like to implement this method in the base class is because of project restrictions. There are a large number of devs working on the derived classes. By implementing this in the base class, I am trying to have 1 less thing for them to worry about.
编辑:我想在基类中实现这个方法的原因是项目限制。有大量开发人员在研究派生类。通过在基类中实现这一点,我试图让他们少担心 1 件事。
回答by mqp
(Assuming that what you want is to compare all the fields of the two objects for equality.)
(假设您想要的是比较两个对象的所有字段是否相等。)
Usually, you wouldn't bother using reflection for this, you'd just compare each field yourself. The IEquatable<T>
interface exists for this purpose, and you also might want to override Object.Equals()
on the types in question. For example:
通常,您不会为此使用反射而烦恼,您只需自己比较每个字段。该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);
}
}
Also, consider whether or not your type makes sense as a struct
instead. Value types automatically compare equality by doing a field-by-field comparison.
另外,请考虑您的类型是否有意义struct
。值类型通过逐字段比较自动比较相等性。
Note that by overriding Equals
, you basically achieve what (it seems to me) you're trying to achieve with your "master equals method" scheme. That is, people using DataTypeTwo
will be able to naturally test for equality without having to know anything special about your API -- they'll just use Equals
like they would with other things.
请注意,通过覆盖Equals
,您基本上实现了(在我看来)您试图通过“主等于方法”方案实现的目标。也就是说,使用的人DataTypeTwo
将能够自然地测试相等性,而无需了解您的 API 的任何特殊之处——他们将Equals
像对待其他事物一样使用。
EDIT: Thanks to Jared for reminding me about GetHashCode
. You'll also want to override it to maintain normal-looking behavior in hashtables by making sure that any two objects which are "equal" also return the same hash code.
编辑:感谢 Jared 提醒我关于GetHashCode
. 您还需要覆盖它以通过确保“相等”的任何两个对象也返回相同的哈希码来保持哈希表中的正常行为。
回答by Daniel Brückner
Yes, you will have to use reflection, because the base class knows nothing about derived classes. But why do you want to implement that function in the base class? Why not in the derived classes?
是的,您将不得不使用反射,因为基类对派生类一无所知。但是为什么要在基类中实现该函数呢?为什么不在派生类中?
Further there is a standard way to do this by overriding Object.GetHashCode() and Object.Equals().
此外,还有一种标准方法可以通过覆盖 Object.GetHashCode() 和 Object.Equals() 来做到这一点。
回答by Svish
I would probably do something like this:
我可能会做这样的事情:
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);
}
}
回答by Chris Persichetti
Here's what I came up with using reflection. Hope it helps.
这是我想出的使用反射的方法。希望能帮助到你。
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;
}
回答by Jorge Córdoba
Don't do it. Inheritance is the way to go and each class, should override the Equal and GetHashCode where needed.
不要这样做。继承是要走的路,每个类都应该在需要的地方覆盖 Equal 和 GetHashCode。
Maybe you'll get some work done out of those developers now but I'll come back to bite you in the ass in the future when the product needs to be maintained.
也许您现在可以从这些开发人员那里完成一些工作,但是将来需要维护产品时,我会回来咬您的屁股。
Seriously, just try to find another way to help.
说真的,只是尝试寻找另一种方式来提供帮助。
回答by Basavakumar R M
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;
}