继承泛型抽象

时间:2015-10-09 09:03:44

标签: c# .net generics inheritance abstract

我不确定这是否可行,需要一些澄清。

我有这样的类结构:

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类中,我想创建一个接受泛型参数的方法,该参数继承自具有两个通用参数的抽象类。类MyFooBarHolderImpl扩展了抽象基类,并使用从抽象类继承的类型指定其泛型参数。通用参数类型。

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

这是根本无法完成的事情,还是我错过了概念/语法?

提前致谢!

3 个答案:

答案 0 :(得分:2)

嗯,它不能直接完成 - FooBarHolderAbstract<Foo, Bar> 不是一个FooBarHolderAbstract<FooBase, BarBase>。目前尚不清楚你是否可以逻辑拥有它,因为我们不知道抽象类中的内容。

您基本上都在寻找generic covariance,但无论如何都不支持课程 - 所以您可能想要引入一个界面:

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>

但是,这仅适用于您可以定义在&#34; out&#34;中使用TV的界面的所有操作。职位,例如从方法返回类型。如果您在&#34;输入&#34;职位,例如作为方法参数,您会陷入困境 - 因为期望Foo的方法无法处理任何其他类型的FooBase

答案 1 :(得分:1)

它不清楚,你要在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>();
    }
}

答案 2 :(得分:0)

您必须如下编写FooBarTest。您必须将T的{​​{1}}定义为DoSomethingWithFooBar<T>

FooBarHolderAbstract<Foo, Bar>