我有例行公事
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”
注意:如果您只使用Guid数组,您将得到相同的错误。仿制药不是原因..。
但!鉴于此
public void SomeRoutine2(IFormattable obj) { ... }还有这个
Guid a = Guid.NewGuid();
SomeRoutine2(a);它会编译!所以问题是为什么?为什么我能够将Guid对象(实现IFormattable)传递给接受IFormattable对象的例程,但是当我试图将它扩展到集合(泛型列表、数组或其他任何东西)时,我会得到一个转换错误。
我花了很长时间才找到答案,我觉得这是最好的去处。
发布于 2009-02-25 00:46:11
这就是每个人都在谈论的全部协变问题。它将在.NET 4.0中工作。
见此处:http://blogs.msdn.com/charlie/archive/2008/10/28/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
再读一读:
http://www.infoq.com/news/2008/08/GenericVariance;jsessionid=188695B18864997E8D360E0EEED5983E
http://blogs.msdn.com/lucian/archive/2008/10/02/co-and-contra-variance-how-do-i-convert-a-list-of-apple-into-a-list-of-fruit.aspx
发布于 2009-02-25 04:39:00
这是一个典型的泛型用例;请尝试:
public static void SomeRoutine<T>(IList<T> list) where T : IFormattable
{ ... }现在,在SomeRoutine内部,您可以访问所有IFormattable成员,但它将使用:
List<Guid>list; ...
SomeRoutine(list); // note no need to specify T编辑:另外,我还介绍了这个场景中4.0协方差和泛型之间的差异。
发布于 2009-02-25 01:26:32
问题是,List不仅是一个可以读取某些IFormattables的集合,也是一个可以添加IFormattables的集合。清单符合第一个要求,但不符合第二个要求。如果SomeRoutine是
public void SomeRoutine(List<IFormattable> list)
{
list.Add(5);
}Int32是一个IFormattable,所以该方法应该能够将它添加到它所要求的列表中。如果编译器允许您传递列表,这是行不通的。
C#所引用的新的BFree 4.0特性将允许您告诉编译器什么时候这些事情是安全的。你可以说
https://stackoverflow.com/questions/584319
复制相似问题