具有泛型 class 的泛型函数:无隐式引用转换
Generic function with generic class: no implicit reference conversion
我正在尝试通过引入通用函数来清理一些重复的代码块。但我没能做到,我感觉我的 class 继承结构变得比我试图清理的代码更混乱...
这里是对所涉及的 classes 的抽象概述:
接口:
interface Ia
interface Ib : Ia
interface Ic : Ib
class是:
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>'.
我猜到错误中的 'implicit' 这个词是指 class 定义中没有 where T : Ib
。所以我又加了一个class
class Cb2<T> : Cb<T> where T : Ib
并使 Cc
继承自 Cb2
而不是 Cb
。但这导致了同样的错误。
谁能解释为什么这是受限的,我该如何解决?
谢谢!
通常 C# 不允许泛型参数替换,即使它们是继承的 类。这在添加 variance 修饰符后发生了变化。
您需要的是协变性,它允许使用派生类型代替泛型参数。但是方差修饰符仅适用于接口和委托,因此 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);
}
}
请注意 Ca
和 Cb
定义中的 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>
我正在尝试通过引入通用函数来清理一些重复的代码块。但我没能做到,我感觉我的 class 继承结构变得比我试图清理的代码更混乱...
这里是对所涉及的 classes 的抽象概述:
接口:
interface Ia
interface Ib : Ia
interface Ic : Ib
class是:
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>'.
我猜到错误中的 'implicit' 这个词是指 class 定义中没有 where T : Ib
。所以我又加了一个class
class Cb2<T> : Cb<T> where T : Ib
并使 Cc
继承自 Cb2
而不是 Cb
。但这导致了同样的错误。
谁能解释为什么这是受限的,我该如何解决?
谢谢!
通常 C# 不允许泛型参数替换,即使它们是继承的 类。这在添加 variance 修饰符后发生了变化。
您需要的是协变性,它允许使用派生类型代替泛型参数。但是方差修饰符仅适用于接口和委托,因此 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);
}
}
请注意 Ca
和 Cb
定义中的 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>