interface作为参数或generics方法与where – 有什么区别?
有什么区别:
public void Method1(class1 c, T obj) where T:Imyinterface
和
public void Method2(class1 c, Imyinterface obj)
?
使用第一种方法有什么好处?
虽然在您的场景中它实际上是相同的(除了使用方法接受接口参数它将具体对象转换为接口类型的事实)考虑稍微不同的场景。 假设我们希望我们的方法只接受实现两个接口IMyInterface1
和IMyInterface2
,否则代码不应该编译:
interface IMyInterface1 { } interface IMyInterface2 { } class MyClass : IMyInterface1 { } public void Method1(Class1 c, T obj) where T : IMyInterface1, IMyInterface2 { }
如果我们创建接受接口的方法作为它的第二个参数它将不满足条件,因为它不会限制用户发送仅实现一个接口的类实例但不实现第二个接口,就像它在MyClass和IMyInterface2中一样例。
用户应该发送什么接口? 他真的不知道需要在编译时发送的类型。
这是使用generics和通用约束的好地方,另一方面我们不能使用单个接口参数。
如上所述,使用void方法,使用方法没有太大差异。
如果您在幕后看,您会看到使用generics方法,.NET将为您调用它的每种类型编译一个单独的方法。 这具有在使用结构调用时避免装箱的效果。
使用返回类型时会出现很大的差异。
public T Method1
和
public IMyinterface Method2(class1 c, IMyInterface obj)
使用通用版本,您将返回原始类型,因此您可以继续调用原始类型的属性或方法(实例或扩展名)。
对于非generics版本,您只返回IMyInterface
类型的值,因此您只能调用属于IMyInterface
属性或方法。
在我的书中,当与扩展方法和流畅的API一起使用时,这是最有趣的。
public static T Move(this T animal) where T : ICanMove { return animal; } public static T Fly (this T animal) where T : ICanFly { return animal; } public static T Pounce (this T animal) where T : ICanPounce { return animal; }
鉴于Tiger实现了ICanMove和ICanPounce,并且Eagle实现了ICanMove和ICanFly,我可以调用适用于原始类型的上述扩展方法。 Intellisense将显示可用于Eagle的.Fly()和.Move(),以及用于Tiger的.Pounce()和.Move()。
var birdie = new Eagle(); birdie .Move() .Fly() .Move() .Fly(); var kitty = new Tiger(); kitty .Move() .Pounce() .Move() .Pounce();
如果您非常地实现Move,那么这就是它的样子:
public static ICanMove Move(this ICanMove animal) { return animal; }
由于返回了ICanMove接口,因此编译器不知道它最初是Eagle或Tiger,因此您只能使用属于ICanMove接口的扩展,方法或属性。
使用通用方法可以为您提供轻微签名更改的各种可能性:
-
public void Method1
:(class1 c, T obj) where T:Imyinterface, new()
这允许实例化类型T的新实例。 -
public T Method1
:(class1 c, T obj) where T:Imyinterface
这允许您在需要时使用该方法而不转换它的返回值。 -
public void Method1
:(class1 c, ref T obj) where T:Imyinterface
这允许您为obj
的引用赋予新值。 同样适用于。
对于非通用版本,这些是不可能的。
void
方法没有太大区别。
public void Method1(class1 c, T obj) where T : Imyinterface
等于
public void Method2(class1 c, Imyinterface obj, Type t)
其中t
必须是Imyinterface
。
因此,如果需要将一些Type
传递给方法,并且需要在编译时对该Type
应用一些约束,请使用generics方法。