为什么我不能将一个Foo<Bar>转换为IFoo<IBar>?

4

为什么无法将 Foo<Bar> 转换为 IFoo<IBar>

如果尝试转换,会出现以下错误:

无法将 Foo<Bar> 隐式引用转换为 IFoo<IBar>


1
Foo是否实现了IFoo接口? - AndrewC
Foo 是否实现了 IFoo 接口,Bar 是否实现了 IBar 接口? - Clive
展示:(1)你对Foo的定义,特别是它实现了哪些接口。(2) 你在尝试“转换”时使用的代码。 - Cheeso
当然,Foo实现了IFoo。 - magol
3个回答

12
如果您使用的是C# 4,并且IFoo声明为以下形式,则它将起作用:
public interface IFoo<out T>

假设Bar实现IBar,而Foo<T>实现IFoo<T>

然而,只有在安全的情况下才能这样声明。如果T值既作为输入又作为输出进入API,则不安全。例如:

public interface IFoo<T>
{
    T Value { get; set; }
}

如果这里是协变的话,那么你就可以写成:

T 不能被协变化,因为这样会有问题:

public class StringFoo : IFoo<string>
{
    public T Value { get; set; }
}

IFoo<string> fooString = new StringFoo(); // That's fine
IFoo<object> fooObject = fooString;       // This isn't, because...
fooObject.Value = new Object();           // ... this would violate type safety

阅读Eric Lippert关于泛型协变和逆变的长篇博客系列,可以获得更多信息。


问题通过在接口声明中添加“out”来解决。谢谢。 - magol

2
为了使这个工作正常,需要满足以下三个条件:
  1. Bar 必须实现 IBar
  2. Foo 必须实现 IFoo
  3. IFoo<T> 必须在 T 上是协变的(像这样:IFoo<out T>

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接