鉴于这些接口和类
public interface IFoo { }
public interface IFooWrapper<I> where I : IFoo { }
public class Foo : IFoo { }
public class FooWrapper : IFooWrapper<Foo> { }
Run Code Online (Sandbox Code Playgroud)
为什么这会失败?
IFooWrapper<IFoo> foo = new FooWrapper();
Run Code Online (Sandbox Code Playgroud)
我知道我可以dynamic在这里使用,但真正的问题是:我有一个方法可以接收这些接口的实现,但由于同样的原因它失败了:
严重性代码说明项目文件行抑制状态错误 CS0266 无法将类型“FooWrapper”隐式转换为“IFooWrapper”。存在显式转换(您是否缺少演员表?)
方法签名看起来像
void Register(IFooWrapper<IFoo> foo)
{
}
Run Code Online (Sandbox Code Playgroud)
编译器在该行失败
Register(new FooWrapper());
Run Code Online (Sandbox Code Playgroud)
那是因为协方差和逆方差。
当某个东西是 a 时IFooWrapper<Foo>,这并不意味着它可以在编译时转换为IFooWrapper<IFoo>. 我认为这里解释得更好:Covariance and Contravariance (C#) | Microsoft Docs并且仍然对 covariance 和 contravariance & in/out 感到困惑。
请注意,您可以将 C# 中的接口标记为协变或逆变。例如,如果您有以下接口(请注意out I- 它现在是类型参数的协变I),您可以使用IFooWrapper<IFoo> foo = new FooWrapper();
public interface IFooWrapper<out I> where I : IFoo { }
Run Code Online (Sandbox Code Playgroud)
查看Fiddle 中的演示
您可以使用泛型修复方法签名,而不是更改接口:
void Register<T>(IFooWrapper<T> foo) where T: IFoo
{
}
Run Code Online (Sandbox Code Playgroud)
可以用IFooWrapper<Foo>and调用那个IFooWrapper<IFoo>- 所以这是有效的:Register(new FooWrapper());
另见小提琴
| 归档时间: |
|
| 查看次数: |
45 次 |
| 最近记录: |