接口作为类型约束和接口作为参数之间的区别?

如果我想创建一个将IList实例作为参数(或任何其他接口,但让我们使用IList作为示例)的方法,我可以创建一个带有类型约束的generics方法,例如:

 public static void Foo1(T list) where T : IList { } 

或者,我可以创建一个直接获取IList参数的方法:

 public static void Foo2(IList list) { } 

出于所有意图和目的,似乎这些方法的行为完全相同:

 List myList = new List(); Foo1(myList); Foo2(myList); 

所以这是我的问题 – 这两种方法之间的区别是什么? 似乎第二种方法稍微可读; 我应该注意哪些其他差异(生成不同的IL等)? 提前致谢。

有几点不同:

  • 如果您再次需要真实类型(例如传递给另一个generics方法或进行日志记录),那么generics方法会更好
  • T可以是值类型,但最终仍然以通用forms取消装箱。 IList不太可能出现这种情况,但对于其他接口来说,这是非常合理的
  • 通用表单允许您指定与实际对象类型不同的具体实现类型。 例如,您可能传入空引用但仍想知道哪个实现类型为T
  • 他们将被不同地JIT; 请参阅Joe Duffy 最近关于generics的博客文章以获取更多信息

这当然取决于你正在做什么……除非你真的需要在方法中知道关于T任何事情,否则通用forms的唯一好处就是拳击点。

如果Foo2返回void,则无关紧要。 但假设Foo2返回了列表的修改版本。 使用IList参数,它能做的最好就是返回另一个IList。 但是使用IList约束,它可以返回调用者想要的任何类型,假设该类型实现了IList

除了所有较低级别的含义之外,当列表被封装并且有修改它的操作时,你谈论的是一个对象而且这个列表不应该暴露(在大多数情况下),因此generics的使用是没有意义的并且在没有正当理由的情况下揭露该类的内部运作。

如果您有一个需要公开列表的数据结构,那么通过generics指定它往往会使数据存在更容易阅读(恕我直言)。

重复你的例子我更喜欢第二种方法。 当调用者可以使用多个类型时,通常使用generics方法或类,如示例中所示。 在这种情况下,您可以避免基类(例如object )作为返回值并提供类型安全返回值。 简单的样本

 public class Foo { public T GetSomething() { return default(T); } } 

简单:

在这里你给出了一个非常简单的例子:因为你已经给了顶级接口ILIST。

但是,

让我说我有一个对象的instanc。

 JimMorrison JohnLennon SnowieWhite 

他们全都来自ILegends

他们都是歌手的对象(var singer = new Singer())

YokOno也是一名歌手,但不是 Ilegends (mmmm ……不知道为什么?)

而你的function可以采取Singer

但是你想确保只有ILegeneds才有效……所以是你的答案。