为了提供类型安全的接口,我编写了以下代码:
namespace MWE
{
public abstract class C {}
public class A : C {}
public class B : C {}
public class Container<T> where T : C
{
public readonly T Value;
public static implicit operator T(Container<C> c)
{
return c.Value;
}
}
public interface IWrapper<out TC> where TC : C {}
public class Foo
{
public Foo(IWrapper<Container<C>> wrapper) {}
}
}
不幸的是,这不编译。 Compiler<C>
-wrapper
构造函数的Foo
参数部分会导致编译器产生以下错误:
类型'MFE.Container <MFE.C>'不能用作泛型类型或方法'IWrapper <TC>'中的类型参数'TC'。没有从'MFE.Container <MFE.C>'到'MFE.C'的隐式引用转换。 类型'MFE.Container <MFE.C>'必须可转换为'WeirdTestStuff.C',以便在通用接口'MFE.IWrapper <out TC>'中将其用作参数'TC'。
我无法确定问题的确切位置,因为转换的协方差似乎存在,甚至存在从Container<T>
到T
定义的隐式转换。自从T : C
以来,我认为它应该像这样工作。
如果可能的话,我想保持Foo
的构造函数。
我希望有人能指出我解决这个问题
甚至是从Container定义的隐式转换
这是事实,但这不是编译器所需要的。这个需要:
隐式引用转换
(我的重点)
隐式引用转换不是由任何用户定义的运算符提供的,只有当一个类型从另一个类型派生(直接或通过中间类型)时才允许。
Container
有一个C
,可以通过用户定义的运算符转换为C
,但这还不足以使它成为C.你的问题太抽象了,无法说明修复应该在这里 - 如果Container
是非泛型的并源自C
?这是“闭嘴”编译器的明显方法,但可能无法解决您的实际问题。
您不能使用泛型来使类型的基类型在运行时可设置。
1这些是Eric Lippert的Representation-preserving conversions