如何获得一个采用泛型类型的类,以便从该类型的实例中调用方法
本文关键字:类型 实例 方法 调用 一个 泛型类型 何获得 | 更新日期: 2023-09-27 18:25:25
我有一个带有以下方法的基类"Entity"(我没有实现IEquatable,这是一个非常头疼的问题,所以我放弃了这种方法)
virtual public bool Equals(Entity entity)
{
throw new Exception("The base Entity.Equals method should never be called");
}
我有几个扩展Entity的类。每一个都将实现一个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.
如何获得一个采用泛型类型的类,以便从该类型的实例中调用方法?
只覆盖基本的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而付出的一个小代价。
给你,这就是你真正需要的。
为了覆盖函数,参数必须同时存在。所以你的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;
}