7

很简单,为什么这段代码编译失败?

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>。为什么不?有没有办法解决?我真的不想诉诸泛型来实现这一点。

4

4 回答 4

1
T : IWorld

表示 T 已经实现了 IWorld,并不意味着它只实现了 IWorld 并且完全是 IWorld。它也可能已经实现了其他接口。

但是,C# 在其更高版本中支持这种转换。请参阅http://msdn.microsoft.com/en-us/library/dd799517.aspx(泛型中的协变和逆变)

于 2012-12-21T10:08:03.763 回答
1

您可以先转换为对象

Foo<IWorld> bar2 = (Foo<IWorld>)(object)new Foo<T>();
于 2012-12-21T10:10:11.977 回答
1

一个更简单的反对意见 - 想象一下,而不是Foo,例如List

将您转换List<T>为 aList<IWorld>后,我现在可以将其他 IWorld一些实现对象(例如 type T2)添加到一个限制为仅包含 type 对象的列表中T。那不应该是有效的。

所以回到你的Foo对象——如果它包含任何期望用 type 的对象调用的方法T,我现在可以用任何实现的对象调用它们IWorld——即使(想象一个额外的类型约束Foo)该对象不是合格的类型为Foo.


我在评论中的观点是:值类型。同样,如果我们从以下方面进行讨论,这可能会更容易List<T>-List<T>值类型包含没有装箱的值类型。如果您想要其中一个List<IWorld>相同的值,则必须先将每个值装箱,然后再将其添加到列表中。

于 2012-12-21T10:44:06.403 回答
0

以下有什么问题

 Foo<IWorld> bar1 = new Foo<IWorld>(); 

你想达到什么目的?

如果您需要传递IWorld实例,您可以安全地传递T,但您的代码中并非如此。

编辑(基于评论)

要投射到Foo<Array of something>您可以使用CastOfType根据您的要求(是否要抛出或忽略不兼容的匹配)。

如果是 .NET 4,由于CoVariance功能,它应该会自动工作。

于 2012-12-21T10:13:10.367 回答