繁体   English   中英

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

[英]Difference between interface as type constraint and interface as parameter?

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

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

}

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

public static void Foo2(IList list)
{

}

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

List<string> myList = new List<string>();
Foo1(myList);
Foo2(myList);

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

有几点不同:

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

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

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

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

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

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

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

简单:

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

但是,

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

JimMorrison
JohnLennon
SnowieWhite

他们都来自ILegends

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

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

而你的功能可以采取Singer

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM