I need to write a generic method in the base class that would accept 2 objects as parameters and compares them for equality.
Ex:
public abstract cla
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;
}
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);
}
}
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;
}
(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:
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.
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.
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.
Don't do it. Inheritance is the way to go and each class, should override the Equal and GetHashCode where needed.
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.
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().