【发布时间】:2020-05-05 04:26:36
【问题描述】:
我的班级层次结构如下:
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
}
}
还有一个类,目的是接收上述层次结构中的对象(当然基类除外),并与它们做一些比较操作:
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;
}
}
}
}
}
通过单元测试和调试,很明显Comparer 没有正确使用上面定义的custom Equals 方法。为什么是这样?它还打算在未来包含一些具有一些集合操作的方法,这将需要Equals。
【问题讨论】:
-
如果比较你得到一个
IssueTypeA和一个IssueTypeB,它会调用哪个Equals方法? -
@YuriyFaktorovich 我没有尝试过。我会这样做,但在正常情况下,
Issue的两种不同子类型不会混合在一起。也许泛型在这里不适合。 -
如果你实现了 IEquatable,你还应该重写 Object.Equals 和 Object.GetHashCode。 Comparer 包括哪些方法?它是否实现接口IComparer?你在Comparer的方法中遇到了什么问题?
-
@IliarTurdushev 我将添加一个包含在
Comparer中的方法示例。 -
@Al2110 现在我看到了
Comparer类的定义中的问题。当您调用spreadsheetRecord.Equals(downloadedIssue)时,会调用方法Object.Equals(而不是IEquatable.Equals),因为Comparer的类型T不会被限制为实现IEquatable。将Comparer的定义更改为下一个:class Comparer<T> where T : Issue, IEquatable<T>。还可以考虑在Issue类中覆盖Object.Equals和Object.GetHashCode。