简体   繁体   English

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

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

If I wanted to create a method that takes an instance of IList as a parameter (or any other interface, but let's use IList as an example), I could create a generic method with a type constraint, eg: 如果我想创建一个将IList实例作为参数(或任何其他接口,但让我们使用IList作为示例)的方法,我可以创建一个带有类型约束的泛型方法,例如:

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

}

Alternatively, I could create a method that takes an IList parameter directly: 或者,我可以创建一个直接获取IList参数的方法:

public static void Foo2(IList list)
{

}

For all intents and purposes, it seems like these methods behave exactly the same: 对于所有意图和目的,似乎这些方法的行为完全相同:

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

So here's my question -- what's the difference between these two approaches? 所以这是我的问题 - 这两种方法之间的区别是什么? It seems like the second approach is slightly more readable; 似乎第二种方法更具可读性; are there any other differences I should be aware of (different IL being generated, etc)? 我应该注意哪些其他差异(生成不同的IL等)? Thanks in advance. 提前致谢。

A couple of differences: 有几点不同:

  • If you ever need the real type again (eg to pass to another generic method or for logging) then the generic method will be better 如果您再次需要真实类型(例如传递给另一个泛型方法或进行日志记录),那么泛型方法会更好
  • T could be a value type and still end up being unboxed in the generic form. T可以是值类型,但最终仍然以通用形式取消装箱。 It's pretty unlikely that this would be the case for IList , but for other interfaces it's highly plausible IList不太可能出现这种情况,但对于其他接口来说,这是非常合理的
  • The generic form allows you to specify a concrete implementation type which is different from the actual object type. 通用表单允许您指定与实际对象类型不同的具体实现类型。 For example, you might pass in a null reference but still want to know which implementation type T is 例如,您可能传入空引用但仍想知道哪个实现类型为T
  • They will be JITted differently; 他们将被不同地JIT; see Joe Duffy's recent blog post on generics for more information 请参阅Joe Duffy 最近关于泛型博客文章以获取更多信息

It really depends on what you're doing of course... unless you actually need to know anything about T within the method, the only benefit to the generic form is the boxing point. 这当然取决于你正在做什么......除非你真的需要在方法中知道关于T任何事情,否则通用形式的唯一好处就是拳击点。

if Foo2 returns void, it doesn't really matter. 如果Foo2返回void,则无关紧要。 But suppose Foo2 returned a modified version of the list. 但是假设Foo2返回了列表的修改版本。 With an IList parameter, the best it could do is return another IList. 使用IList参数,它能做的最好就是返回另一个IList。 But with an IList constraint, it could return any type the caller wants assuming that type implements IList 但是使用IList约束,它可以返回调用者想要的任何类型,假设该类型实现了IList

Aside from all the lower-level implications, when the list is encapsulated and there are operations to modify it, you're talking about an object and this list shouldn't be exposed (in most cases), therefore the use of generics are pointless and expose, without a valid reason, the inner workings of the class. 除了所有较低级别的含义之外,当列表被封装并且有修改它的操作时,你谈论的是一个对象而且这个列表不应该暴露(在大多数情况下),因此使用泛型是没有意义的并且在没有正当理由的情况下揭露该类的内部运作。

If you have a data structure that needs to expose the list, then specifying it by generics tend to make the data presence easier to read (IMHO). 如果您有一个需要公开列表的数据结构,那么通过泛型指定它往往会使数据存在更容易阅读(恕我直言)。

Reagrding your example I would prefer the second approach. 重复你的例子我更喜欢第二种方法。 Generic methods or classes are mostly used when the caller can use them with more than on type as in your example. 当调用者可以使用多个类型时,通常使用通用方法或类,如示例中所示。 In this case you can avoid a base class (eg object ) as return value and provide type safe return values. 在这种情况下,您可以避免基类(例如object )作为返回值并提供类型安全返回值。 On simple sample 简单的样本

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

Simple : 简单:

here you gave a pretty easy example : since you already gave the top interface ILIST. 在这里你给出了一个非常简单的例子:因为你已经给了顶级接口ILIST。

but , 但是,

lets say i have an instanc Of Objects. 让我说我有一个对象的instanc。

JimMorrison
JohnLennon
SnowieWhite

they are all from ILegends . 他们都来自ILegends

they are all singers objects ( var singer = new Singer()) 他们都是歌手的对象(var singer = new Singer())

YokOno is also a singer but not Ilegends ( mmmm ... wonder why?) YokOno也是一名歌手,但不是 Ilegends (mmmm ......不知道为什么?)

and your function can take Singer . 而你的功能可以采取Singer

but you want to make sure that only ILegeneds will be valid... so here is your answer. 但是你想确保只有ILegeneds才有效......所以是你的答案。

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

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