我有两个接口(interface),其中一个是通用接口(interface),只允许从第二个接口(interface)派生的类型。它们看起来像这样:
public interface IProvider<T> where T : IContent
{
T getContent(int i);
void addContent(T content);
}
public interface IContent
{
string whatIAm();
}
当然,我的真实接口(interface)更复杂,但足以说明我的问题是什么。
现在我为每个接口(interface)都有一个具体的类:
public class Provider : IProvider<FileContent>
{
public FileContent getContent(int i)
{
return null;
}
public void addContent(FileContent content)
{
}
}
public class FileContent : IContent{
public string whatIAm(){
return "FileContent";
}
}
在我的代码中,我想使用引用类型“IProvider”,但转换出错了......请看这个例子:
static void Main(string[] args)
{
Provider p = new Provider(); //works
IProvider<FileContent> pp = p as IProvider<FileContent>; //also works
IProvider<IContent> ppp = pp as IProvider<IContent>; //fails :(
}
ppp
始终为空。我必须改变这个 Actor 阵容的工作吗?提前致谢。
最佳答案
类型参数必须完全匹配。 IProvider<IContent>
是与 IProvider<FileContent>
不同的类型,它们之间没有继承关系。
想象一下,您有一个 IProvider<IContent> ppp
来自您的IProvider<FileContent>
开发人员尝试 ppp.addContent(someOtherContentThatIsNoFileContent)
.该声明适用于 IProvider<IContent>
,但它会破坏类型安全,因此不允许这样的转换是正确的做法。
Covariance and Contravariance for generic type parameters在某些情况下允许这样的事情,但是由于您的接口(interface)使用类型参数作为输入参数和输出参数,这不适用于它现在声明的方式。
编辑:看IEnumerable
的定义:
public interface IEnumerable<out T>
所以你知道 IEnumerable 使用
T
仅作为输出参数(您不能添加项目,只能枚举它们),以及 out
关键字指定 T
是协变的。所以你可以做IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
如果你想这样做,你必须删除
add
从您的界面中获取方法。同样适用于输入参数和 in
泛型类型参数的关键字。您的界面将如下所示:
public interface IProvider<out T> where T : IContent
{
T getContent(int i);
}
关于.NET 4.0 Cast 通用接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11522420/