如何获得一个采用泛型类型的类,以便从该类型的实例中调用方法

本文关键字:类型 实例 方法 调用 一个 泛型类型 何获得 | 更新日期: 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;
}