C#.NET将一组InterfaceImplementingClass对象传递给一个采用Interface对象集合的例程

emk*_*tra 5 .net c# generics clr interface

我有一个例程

public void SomeRoutine(List<IFormattable> list) { ... }
Run Code Online (Sandbox Code Playgroud)

然后我尝试调用这个例程

List<Guid>list = new List<Guid>();
list.Add(Guid.NewGuid());
SomeRoutine(list);
Run Code Online (Sandbox Code Playgroud)

并且它因编译时错误而失败.System.Guid实现了IFormattable,但我得到的错误是

无法从'System.Collections.Generic.List'转换为'System.Collections.Generic.List'

注意:如果您只使用Guids数组,则会出现相同的错误.泛型不是原因....

但!鉴于这种

public void SomeRoutine2(IFormattable obj) { ... }
Run Code Online (Sandbox Code Playgroud)

还有这个

Guid a = Guid.NewGuid();
SomeRoutine2(a);
Run Code Online (Sandbox Code Playgroud)

它汇编!所以问题是为什么?为什么我能够将Guid对象(实现IFormattable)传递给接受IFormattable对象的例程,但是当我尝试将其扩展到集合(通用列表,数组或其他任何东西)时,我得到了转换错误?

我有一段时间找到答案,我认为这将是最好的去处.

Mar*_*ell 5

这是一个经典的泛型用例; 尝试:

public static void SomeRoutine<T>(IList<T> list) where T : IFormattable
{ ... }
Run Code Online (Sandbox Code Playgroud)

现在SomeRoutine你可以访问所有IFormattable成员,但它可以使用:

List<Guid>list; ...
SomeRoutine(list); // note no need to specify T
Run Code Online (Sandbox Code Playgroud)

编辑:我还在博客上讨论了此方案的4.0协方差和泛型之间的差异.