c#中的强制转换约束泛型类
本文关键字:转换 约束 泛型类 | 更新日期: 2023-09-27 17:49:14
很简单,为什么这段代码无法编译?
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(泛型中的协方差和逆变性)
可以先强制转换为object
Foo<IWorld> bar2 = (Foo<IWorld>)(object)new Foo<T>();
一个更简单的反对意见——想象一下,这不是Foo
,而是List
。
将List<T>
转换为List<IWorld>
后,我现在可以将一些其他 IWorld
实现对象(例如T2
类型)添加到约束为仅包含T
类型对象的列表中。这应该是无效的。
所以回到你的Foo
对象-如果它包含任何方法,期望与T
类型的对象调用,我现在可以调用任何对象实现IWorld
-即使(想象Foo
的附加类型约束)该对象将不是Foo
的合格类型。
我在评论中的观点是:值类型。同样,如果我们用List<T>
来讨论,这可能会更容易——值类型的List<T>
包含没有装箱的值类型。如果您想要这些相同值的List<IWorld>
,每个值必须在添加到列表之前框。
以下内容有什么问题
Foo<IWorld> bar1 = new Foo<IWorld>();
你想达到什么目标?
如果你需要传递IWorld
实例,你可以安全地传递T
,但在你的代码中不是这样的。
编辑(基于注释)
要转换为Foo<Array of something>
,可以根据需要使用cast或OfType(是否要抛出或忽略不兼容的匹配)。
如果是。net 4,由于协方差特性,它应该自动工作。