继承通用抽象

Inheriting generic abstract

我不确定这是否可行,希望得到一些说明。

我有这样的 class 结构:

public class FooBase
{
    //Some base class
}

public class BarBase
{
    //Some base class    
}

public class Foo : FooBase
{
    //Implementation
}

public class Bar : BarBase
{
    //Implementation
}

public abstract class FooBarHolderAbstract<T, V> where T: FooBase where V: BarBase
{
}

public class MyFooBarHolderImpl : FooBarHolderAbstract<Foo, Bar>
{
}

public class FooBarTest
{
    public void DoSomethingWithFooBar<T>() where T : FooBarHolderAbstract<FooBase, BarBase>
    {
        //Do something tith the obj
    }

    public void RunTest()
    {
        //This doesn't work, compiler says MyFooBarHolder is not convertible to FooBarHolderAbstract<FooBase, BarBase>
        DoSomethingWithFooBar<MyFooBarHolderImpl>();
    }
}

在 FooBarTest class 中,我想创建一个接受泛型参数的方法,它继承自具有两个泛型参数的抽象 class。 class MyFooBarHolderImpl 扩展了抽象基础 class 并使用从抽象 class 的泛型参数类型继承的类型指定其泛型参数。

当我尝试调用此方法 (DoSomethingWithFooBar()) 时,编译器告诉我类型 MyFooBarHolderImpl 必须可转换为 FooBarHolderAbstract

这是根本无法完成的事情,还是我错过了 concept/syntax?

提前致谢!

嗯,这不能直接完成 - FooBarHolderAbstract<Foo, Bar> 不是 FooBarHolderAbstract<FooBase, BarBase>。不清楚您是否可以逻辑上 拥有它,因为我们不知道摘要中的内容 class.

你基本上是在寻找 generic covariance,但 classes 不支持它 - 所以你可能想引入一个接口:

public interface IFooBarHolder<out T, out V>
    where T: FooBase
    where V: BarBase
{
    // Define what you need in here
}

public abstract class FooBarHolderAbstract<T, V> : IFooBarHolder<T, V>
    where T : FooBase
    where V : BarBase
{

}

此时,您可以将 FooBarTest 更改为:

public void DoSomethingWithFooBar<T>() where T : IFooBarHolder<FooBase, BarBase>
{
    //Do something with the obj
}

...因为 IFooBarHolder<Foo, Bar> IFooBarHolder<FooBase, BarBase>.

但是,这仅在您可以为在 "out" 位置使用 TV 的接口定义所有操作时才有效,例如return 来自方法的类型。如果您在 "input" 个位置需要它们,例如作为方法参数,你被卡住了——因为期望 Foo 的方法无法处理任何其他类型的 FooBase.

您必须FooBarTest如下所示。您必须将 DoSomethingWithFooBar<T>T 定义为 FooBarHolderAbstract<Foo, Bar>

    public class FooBarTest
    {
        public void DoSomethingWithFooBar<T>() where T : FooBarHolderAbstract<Foo, Bar>
        {
            //Do something tith the obj
        }

        public void RunTest()
        {                         
            DoSomethingWithFooBar<MyFooBarHolderImpl>();
        }
    }

不清楚,你要在 DoSomethingWithFooBar 中做什么,因为你没有传递任何参数,但这里有另一个选项:

public class FooBarTest
{
    public void DoSomethingWithFooBar<TFooBase, TBarBase>(FooBarHolderAbstract<TFooBase, TBarBase> obj) 
        where TFooBase : FooBase
        where TBarBase : BarBase
    {
        //Do something tith the obj
    }

    public void RunTest()
    {
        DoSomethingWithFooBar<Foo, Bar>(new MyFooBarHolderImpl());
    }
}

public class FooBarTest
{
    public void DoSomethingWithFooBar<TFooBase, TBarBase, THolder>() 
        where TFooBase : FooBase
        where TBarBase : BarBase
        where THolder : FooBarHolderAbstract<TFooBase, TBarBase>
    {
        //Do something tith the obj
    }

    public void RunTest()
    {
        DoSomethingWithFooBar<Foo, Bar, MyFooBarHolderImpl>();
    }
}