I have a class heirarchy as follows:
public abstract class Issue { // some base properties // these are not included in equality checks for deriving classes // also not performing equality checks on this base class (it is abstract anyway) } public class IssueTypeA : Issue, IEquatable<IssueTypeA> { // some properties specific to this class // these are the two for which equality comparison is performed public string requirement { get; set; } public string preamble { get; set; } public bool Equals(IssueTypeA that) { // determine based on the values of the properties // they must both be the same for equality if ((this.requirement.Equals(that.requirement)) && (this.preamble.Equals(that.preamble))) { return true; } return false; } } public class IssueTypeB : Issue, IEquatable<IssueTypeB> { // some properties specific to this class public bool Equals(IssueTypeB that) { // determine based on the values of the properties } } There is another class, intended to receive objects in the above heirarchy (except the base class, of course), and do some comparison operations with them:
public class Comparer<T> where T : Issue { // various comparison methods public IEnumerable<T> getReferenceChangedIssues(IEnumerable<T> spreadsheetIssues, IEnumerable<T> downloadedIssues) { foreach (T spreadsheetRecord in T spreadsheetIssues) { foreach (T downloadedIssue in downloadedIssues) { // this is the point of failure // there are cases in which this should be true, but it is not if (spreadsheetRecord.Equals(downloadedIssue)) { // the referenceChanged method works fine by itself // it has been unit tested if (spreadsheetRecord.referenceChanged(downloadedIssue)) yield return spreadsheetRecord; } } } } } Through unit testing and debugging, it's apparent that the custom Equals methods defined above are not being used correctly by Comparer. Why is this? It is also intended to include methods with some set operations in the future, which will need Equals.
IssueTypeAand oneIssueTypeB, whichEqualsmethod would it call?Issuewould not be mixed. Perhaps generics are not suitable here.Comparer.Comparer. When you callspreadsheetRecord.Equals(downloadedIssue)a methodObject.Equalsis invoked (instead ofIEquatable.Equals), because typeTofComparerdoes not constrained to implementIEquatable. Change the definition of theComparerto the next:class Comparer<T> where T : Issue, IEquatable<T>. And also consider overridingObject.EqualsandObject.GetHashCodein yourIssueclasses.