如何获取一个采用泛型类的类,从该类型的实例调用一个方法?

时间:2014-10-01 20:25:43

标签: c# generics override

我有一个基类“实体”,使用以下方法(我没有实现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。

如何获取一个采用泛型类的类,从该类型的实例调用一个方法?

2 个答案:

答案 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;
}