C# 和使用泛型的多种类型的继承链

C# and inheritance chain of multiple types using generics

我有这个设置,但它没有像我预期的那样工作。在我看来,基础 class 中的通用 T 与其子 class.

中的通用 T 不同
namespace WhosebugQuestion
{
    public class Poco1
    {
        public string Data { get; set; }
    }

    public class Poco2 : Poco1
    {
        public string ExtraData { get; set; }
    }

    public class Poco3 : Poco2
    {
        public string EvenMoreData { get; set; }
    }


    public class Base<T> where T: Poco1
    {
        public virtual void Method(T parameter)
        {
            // Do something even more general with Data...
            parameter.Data = "Test";
        }
    }

    public class FirstLevel<T> : Base<Poco2> where T:Poco2
    {
        public override void Method(Poco2 parameter)
        {
            // Do something general with ExtraData...
            base.Method(parameter);
        }
    }

    public class SecondLevel<T> : FirstLevel<Poco3> where T: Poco3
    {
        public override void Method(Poco2 parameter)  // <-- Why not Poco3?
        {
            // Do something with EvenMoreData...
            base.Method(parameter);
        }
    }
}

我实际期望的是类型 SecondLevel<T> 中的 Method 覆盖应该说 Poco3 而不是 Poco2。特别是当我将 T 限制为 Poco3.

类型时

是否可以通过其他方式实现?在我看来,通用 T 不能像我想要的那样 "overridden" 。我怀疑 Base<T> 中的 T 与 FirstLevel<T> 中的 T 不同,并且 FirstLevel<T> 中的 T 与 SecondLevel<T> 中的 T 不同?

如果 SecondLevel<T> 继承自 Base<T>,那么我会在 Method 覆盖中得到 Poco3,但当我继承自 FirstLevel<T> 时则不会。

我可以忍受这个问题,但我需要在 Level-type sub-classes(从级别 2 及以上)中转换 poco 参数类型。在我看来,只要我指定了约束,那应该是不必要的。但是,当然,我目前看不到这种行为的充分理由。

您可以使用 T 类型参数,而不是在每个重写的方法签名中指定 POCO 类型。

T 已被限制为您想要的 POCO 类型,因此它的行为应该完全符合您的要求。

哦,我也会对你传递给基础的类型做同样的事情 class。

例如

public class FirstLevel<T> : Base<T> where T:Poco2
{
    public override void Method(T parameter)
    {
        // Do something general with ExtraData...
        base.Method(parameter);
    }
}

public class SecondLevel<T> : FirstLevel<T> where T: Poco3
{
    public override void Method(T parameter)
    {
        // Do something with EvenMoreData...
        base.Method(parameter);
    }
}