带有泛型类的泛型函数:没有隐式引用转换

本文关键字:转换 引用 函数 泛型类 泛型 | 更新日期: 2023-09-27 18:05:14

我试图通过引入泛型函数来清理一些重复的代码块。但是我没有设法做到这一点,我有一种感觉,我的类继承结构变得比我试图清理的代码更混乱…

下面是所涉及类的抽象概述:

接口:

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。但这导致了同样的错误。

谁能解释一下为什么这是受限的,我该如何解决它?

谢谢!

带有泛型类的泛型函数:没有隐式引用转换

一般情况下c#不允许泛型参数替换,即使它们是继承的类。当添加方差修饰符时,情况发生了变化。

你需要的是所谓的协方差,它允许使用派生类型来代替泛型参数。但是方差修饰符只在接口和委托上工作,所以Ca, Cb, Cc应该是接口来允许这一点。最接近的是:

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);
    }
}

注意CaCb定义中的out T

关于我们的修饰语

要使这段代码工作,您需要使用一个接口来启用协方差,正如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>