我有例行公事
public void SomeRoutine(List<IFormattable> list) { ... }
然后我尝试调用此例程
List<Guid>list = new List<Guid>();
list.Add(Guid.NewGuid());
SomeRoutine(list);
它因编译时错误而失败。 System.Guid实现了IFormattable,但我得到的错误是
无法转换 'System.Collections.Generic.List' 至 'System.Collections.Generic.List'
注意:如果您只使用Guids数组,则会出现相同的错误。泛型不是原因......
但是!鉴于此
public void SomeRoutine2(IFormattable obj) { ... }
和这个
Guid a = Guid.NewGuid();
SomeRoutine2(a);
它汇编!所以问题是为什么?为什么我能够将Guid对象(实现IFormattable)传递给接受IFormattable对象的例程,但是当我尝试将其扩展到集合(通用列表,数组或其他任何东西)时,我得到了转换错误?
我有一段时间找到答案,我认为这将是最好的去处。
答案 0 :(得分:8)
这是每个人都在谈论的整个协方差事。它将在.NET 4.0中运行。
更多阅读:
http://www.infoq.com/news/2008/08/GenericVariance;jsessionid=188695B18864997E8D360E0EEED5983E
答案 1 :(得分:5)
这是一个经典的泛型用例;尝试:
public static void SomeRoutine<T>(IList<T> list) where T : IFormattable
{ ... }
现在在SomeRoutine
内,您可以访问所有IFormattable
成员,但它可以使用:
List<Guid>list; ...
SomeRoutine(list); // note no need to specify T
编辑:我还有blogged关于此方案的4.0协方差和泛型之间的差异。
答案 2 :(得分:3)
问题在于List&lt; IFormattable&gt;不仅是一个集合,您可以从中读取一些IFormattables,它也是一个可以添加IFormattables的集合。列表&lt; Guid&gt;符合第一个要求,但不是第二个要求。如果SomeRoutine
怎么办?public void SomeRoutine(List<IFormattable> list)
{
list.Add(5);
}
Int32是一个IFormattable,因此该方法应该能够将它添加到List&lt; IFormattable&gt;它要求的。如果编译器允许您传入List&lt; Guid&gt;。
,那么这不会起作用BFree引用的新C#4.0功能将让您在这些事情安全时告诉编译器。你可以说
答案 3 :(得分:2)
您是否尝试将list
声明为List<IFormattable>
个对象而不是List<Guid>
?这应该让你超过编译错误。