很简单,为什么这段代码无法编译?
public interface IWorld { }
public class Foo<T> where T : IWorld { }
public void Hello<T>(T t) where T : IWorld
{
Foo<IWorld> bar1 = new Foo<T>(); //fails implicit cast
Foo<IWorld> bar2 = (Foo<IWorld>)new Foo<T>(); //fails explicit cast
}
由于每个T
实施IWorld
,Foo<T>
的每个实例都应与Foo<IWorld>
匹配。为什么不?有没有办法解决?我真的不想诉诸于泛型来实现这一点。
答案 0 :(得分:1)
T : IWorld
意味着T已经实施了IWorld,并不意味着它只实现了IWorld,而且确实是IWorld。它也可能已经实现了其他接口。
但是,C#在其更高版本中支持此演员。请参阅http://msdn.microsoft.com/en-us/library/dd799517.aspx(泛型中的协方差和反演)
答案 1 :(得分:1)
您可以先转换为对象
Foo<IWorld> bar2 = (Foo<IWorld>)(object)new Foo<T>();
答案 2 :(得分:1)
更简单的反对意见 - 想象一下,Foo
代替List
,而不是List<T>
。
将List<IWorld>
转换为IWorld
后,我现在可以添加一些其他 T2
实施对象(比如类型T
)限制为仅包含Foo
类型的对象的列表。这不应该是有效的。
回到你的T
对象 - 如果它包含任何期望用IWorld
类型的对象调用的方法,我现在可以用任何对象调用它们实现Foo
- 即使(想象Foo
的其他类型约束)该对象也不是List<T>
的合格类型。
我在评论中的观点:价值类型。同样,如果我们用List<T>
来讨论,这可能会更容易 - 对于值类型,List<IWorld>
包含没有装箱的值类型。如果您想要{{1}}这些相同的值,则每个值必须装箱才能添加到列表中。
答案 3 :(得分:0)
以下
有什么问题 Foo<IWorld> bar1 = new Foo<IWorld>();
你想要达到什么目的?
如果您需要传递IWorld
个实例,则可以安全地传递T
,但代码中并非如此。
编辑(根据评论)
要转换为Foo<Array of something>
,您可以使用Cast或OfType,具体取决于您的要求(无论您是要抛弃还是忽略不兼容的匹配)。
如果它是.NET 4,它应该由于CoVariance功能而自动运行。