[英]Casting constrained generic class in C#
很简单,为什么这段代码无法编译?
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>
匹配。 为什么不? 有没有办法解决? 我真的不想借助于泛型来实现这一目标。
T : IWorld
意味着T已经实施了IWorld,并不意味着它只实现了IWorld,而且确实是IWorld。 它也可能已经实现了其他接口。
但是,C#在其更高版本中支持此演员。 请参阅http://msdn.microsoft.com/en-us/library/dd799517.aspx (泛型中的协方差和反演)
您可以先转换为对象
Foo<IWorld> bar2 = (Foo<IWorld>)(object)new Foo<T>();
一个更简单的反对意见 - 想象一下,而不是Foo
,这就是List
。
将List<T>
转换为List<IWorld>
,我现在可以将一些其他 IWorld
实现对象(比如T2
类型)添加到一个列表中,该列表仅限于包含T
类型的对象。 这不应该是有效的。
所以回到你的Foo
对象 - 如果它包含任何期望用类型T
对象调用的方法,我现在可以用任何实现IWorld
对象来调用它们 - 即使(想象一下Foo
的另一个类型约束)该对象也不会是Foo
的合格类型。
我在评论中的观点re:值类型。 同样,如果我们按照List<T>
讨论,这可能会更容易 - 值类型的List<T>
包含没有装箱的值类型。 如果您需要具有这些相同值的List<IWorld>
,则必须在将每个值添加到列表之前将其装箱 。
以下是什么问题
Foo<IWorld> bar1 = new Foo<IWorld>();
你想要实现什么目标?
如果你需要传递IWorld
实例,你可以安全地传递T
,但在你的代码中并非如此。
编辑 (根据评论)
要转换为Foo<Array of something>
您可以根据您的要求使用Cast或OfType (无论您是要抛出还是忽略不兼容的匹配)。
如果它是.NET 4,它应该由于CoVariance功能自动工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.