具有泛型类的泛型函数:无隐式引用转换

时间:2015-07-29 10:46:26

标签: c# generics implicit

我正在尝试通过引入通用函数来清理一些重复的代码块。但我没有设法这样做,我觉得我的类继承结构比我想要清理的代码变得更加混乱......

以下是所涉及课程的摘要概述:

接口:

interface Ia
interface Ib : Ia
interface Ic : Ib

类:

class Ca<T> where T : Ia
class Cb<T> : Ca<T> where T : Ia
class Cc : Cb<Ic>

功能:

void F<T>(T t) where T : Ca<Ib>

无效的函数调用:

F<Cc>(my_c);

错误:

The type 'Cc' cannot be used as type parameter 'T' in the generic type or method 'F<T>(T)'. There is no implicit reference conversion from 'Cc' to 'Ca<Ib>'.

我在错误中猜到了“隐含”这个词,我指的是类定义中没有where T : Ib的事实。所以我添加了另一个类

class Cb2<T> : Cb<T> where T : Ib

并使Cc继承自Cb2而非Cb。但这导致了同样的错误。

任何人都可以解释为什么这是受限制的,以及我如何解决它?

谢谢!

2 个答案:

答案 0 :(得分:2)

通常,C#不会使通用参数替换,即使它们是继承类。添加variance修饰符后,此更改。

您需要的是协方差,它可以使用派生类型代替泛型参数。但是,方差修饰符仅适用于接口和委托,因此CaCbCc应该是允许此接口的接口。你可以得到的最接近的是:

interface Ia {}
interface Ib : Ia {}
interface Ic : Ib {}

interface Ca<out T> where T : Ia {}
interface Cb<out T> : Ca<T> where T : Ia {}
interface Cc : Cb<Ic> {}

class Main
{
    void F<T>(T t) where T : Ca<Ib>
    {}

    void M()
    {
      F<Cc>(null);
    }
}

out TCa定义中注意Cb

More about out modifier

答案 1 :(得分:0)

为了使这个代码有效,你需要使用一个接口来启用协方差,正如Pavel之前所说的那样。你只需要一个最高级别。

interface ICa<out T> where T : Ia
class Ca<T> : ICa<T> where T : Ia
class Cb<T> : Ca<T> where T : Ia
class Cc : Cb<Ic>

方法签名应该是这样的

void F<T>(T t) where T : ICa<Ib>