Comparing two instances of a class
One way of doing it is to implement IEquatable<T>
public class TestData : IEquatable<TestData>
{
public string Name {get;set;}
public string type {get;set;}
public List<string> Members = new List<string>();
public void AddMembers(string[] members)
{
Members.AddRange(members);
}
public bool Equals(TestData other)
{
if (this.Name != other.Name) return false;
if (this.type != other.type) return false;
// TODO: Compare Members and return false if not the same
return true;
}
}
if (testData1.Equals(testData2))
// classes are the same
You can also just override the Equals(object) method (from System.Object), if you do this you should also override GetHashCode see here
There are three ways objects of some reference type T
can be compared to each other:
- With the
object.Equals
method - With an implementation of
IEquatable<T>.Equals
(only for types that implementIEquatable<T>
) - With the comparison operator
==
Furthermore, there are two possibilities for each of these cases:
- The static type of the objects being compared is
T
(or some other base ofT
) - The static type of the objects being compared is
object
The rules you absolutely need to know are:
- The default for both
Equals
andoperator==
is to test for reference equality - Implementations of
Equals
will work correctly no matter what the static type of the objects being compared is IEquatable<T>.Equals
should always behave the same asobject.Equals
, but if the static type of the objects isT
it will offer slightly better performance
So what does all of this mean in practice?
As a rule of thumb you should use Equals
to check for equality (overriding object.Equals
as necessary) and implement IEquatable<T>
as well to provide slightly better performance. In this case object.Equals
should be implemented in terms of IEquatable<T>.Equals
.
For some specific types (such as System.String
) it's also acceptable to use operator==
, although you have to be careful not to make "polymorphic comparisons". The Equals
methods, on the other hand, will work correctly even if you do make such comparisons.
You can see an example of polymorphic comparison and why it can be a problem here.
Finally, never forget that if you override object.Equals
you must also override object.GetHashCode
accordingly.
You should implement the IEquatable<T>
interface on your class, which will allow you to define your equality-logic.
Actually, you should override the Equals
method as well.
public class TestData : IEquatable<TestData>
{
public string Name {get;set;}
public string type {get;set;}
public List<string> Members = new List<string>();
public void AddMembers(string[] members)
{
Members.AddRange(members);
}
// Overriding Equals member method, which will call the IEquatable implementation
// if appropriate.
public override bool Equals( Object obj )
{
var other = obj as TestData;
if( other == null ) return false;
return Equals (other);
}
public override int GetHashCode()
{
// Provide own implementation
}
// This is the method that must be implemented to conform to the
// IEquatable contract
public bool Equals( TestData other )
{
if( other == null )
{
return false;
}
if( ReferenceEquals (this, other) )
{
return true;
}
// You can also use a specific StringComparer instead of EqualityComparer<string>
// Check out the specific implementations (StringComparer.CurrentCulture, e.a.).
if( EqualityComparer<string>.Default.Compare (Name, other.Name) == false )
{
return false;
}
...
// To compare the members array, you could perhaps use the
// [SequenceEquals][2] method. But, be aware that [] {"a", "b"} will not
// be considerd equal as [] {"b", "a"}
return true;
}
}