我有一个基类“实体”,使用以下方法(我没有实现IEquatable,这是一个非常令人头痛的问题所以我放弃了这种方法)
virtual public bool Equals(Entity entity)
{
throw new Exception("The base Entity.Equals method should never be called");
}
我有几个扩展实体的类。每个人都会实现一个Equals方法,就像这样。
virtual public bool Equals(TestPlan other)
{
if (this.TestPlanType.Equals(other.TestPlanType) &&
this.Name.Equals(other.Name) &&
this.Description.Equals(other.Description) &&
this.DatetimeCreated.Equals(other.DatetimeCreated) &&
this.UserNameCreated.Equals(other.UserNameCreated) &&
this.Duration.Equals(other.Duration) &&
this.Scenarios.SequenceEqual(other.Scenarios)) return true;
return false;
}
我真的希望输入的类型是TestPlan而不是Object。 (至少我认为我这样做,我不想失去强力打字)。
我意识到这个方法没有“覆盖”基类,因为我把它设为虚拟公共而不是公共覆盖。
我有一个方法,它采用一个将调用.Equals()
的泛型类型 public int GetIdenticalEntityId<T>(T entity) where T : Entity
{
List<T> exitingEntities = LoadEntities<T>();
foreach (T existingEntity in exitingEntities)
{
if (existingEntity.Equals(entity))
{
return existingEntity.Id;
}
}
return -1;
}
问题是exitingEntity.Equals()调用基类.Equals。
如何获取一个采用泛型类的类,从该类型的实例调用一个方法?
答案 0 :(得分:3)
只需覆盖基础Equals(object other)
方法即可。这很简单。
您甚至可以通过在Entity
课程中声明这一点来强制执行此操作:
public override abstract bool Equals(object other);
public override abstract int GetHashCode();
现在,在您的课程中,Equals
方法将如下所示:
public override bool Equals(object obj)
{
var other = obj as TestPlan;
if (other == null)
return false;
if (ReferenceEquals(other, this))
return true;
return this.TestPlanType.Equals(other.TestPlanType) &&
this.Name.Equals(other.Name) &&
this.Description.Equals(other.Description) &&
this.DatetimeCreated.Equals(other.DatetimeCreated) &&
this.UserNameCreated.Equals(other.UserNameCreated) &&
this.Duration.Equals(other.Duration) &&
this.Scenarios.SequenceEqual(other.Scenarios));
}
现在,如果您想要实施IEquatable<T>
,那么真的很容易:
public bool Equals(TestPlan obj)
{
return Equals((object)obj);
}
你也可以这样做:
public override bool Equals(object obj)
{
return Equals(obj as TestPlan);
}
public bool Equals(TestPlan obj)
{
if (obj == null)
return false;
// Same code as before
}
哦,你也应该实施GetHashCode
以避免令人讨厌的意外:
public override int GetHashCode()
{
var hash = TestPlanType.GetHashCode();
hash = (hash * 397) ^ Name.GetHashCode();
hash = (hash * 397) ^ Description.GetHashCode();
hash = (hash * 397) ^ DatetimeCreated.GetHashCode();
hash = (hash * 397) ^ UserNameCreated.GetHashCode();
hash = (hash * 397) ^ Duration.GetHashCode();
hash = (hash * 397) ^ Scenarios.GetHashCode();
return hash;
}
这非常很重要。有一天,团队中的某个人可能希望将对象用作字典中的键。如果您从一开始就正确实现了GetHashCode
函数,那么您将在以后的代码中避免使用此类陷阱。这是今天为避免大型WTF而付出的小代价。
你走了,这就是你真正需要的。
答案 1 :(得分:0)
为了覆盖函数,参数必须是同一时间。所以你的TestPlan.Equals应该类似于:
override public bool Equals(Entity entity)
{
TestPlan other = entity as TestPlan;
if (other == null)
return false;
if (this.TestPlanType.Equals(other.TestPlanType) &&
this.Name.Equals(other.Name) &&
this.Description.Equals(other.Description) &&
this.DatetimeCreated.Equals(other.DatetimeCreated) &&
this.UserNameCreated.Equals(other.UserNameCreated) &&
this.Duration.Equals(other.Duration) &&
this.Scenarios.SequenceEqual(other.Scenarios)) return true;
return false;
}