public void Method1<T>(class1 c, T obj) where T:Imyinterface
和
public void Method2(class1 c, Imyinterface obj)
?
使用第一种方法的好处是什么?
如前所述,对于void方法,在用法上没有太大区别。
如果你看一下幕后,你会发现对于泛型方法,. net将为你调用它的每种类型编译一个单独的方法。这可以避免在使用struct调用时装箱。
使用返回类型时,最大的区别就出现了。
public T Method1<T>(class1 c, T obj) where T: IMyInterface
和
public IMyinterface Method2(class1 c, IMyInterface obj)
对于泛型版本,您将获得原始类型,因此您可以继续在原始类型上调用属性或方法(实例或扩展)。
对于非泛型版本,您只能获得类型IMyInterface
的值,因此您只能调用属于IMyInterface
的属性或方法。
在我的书中,当与扩展方法和流畅风格的API一起使用时,这是最有趣的。
public static T Move<T>(this T animal) where T : ICanMove
{
return animal;
}
public static T Fly<T>(this T animal) where T : ICanFly
{
return animal;
}
public static T Pounce<T>(this T animal) where T : ICanPounce
{
return animal;
}
假设老虎实现了ICanMove和ICanPounce,老鹰实现了ICanMove和ICanFly,我可以调用上面应用于原始类型的扩展方法。智能感知将显示。fly()和。move()适用于鹰,。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<T>(this ICanMove animal)
{
return animal;
}
由于返回的是ICanMove接口,编译器不知道它原来是Eagle还是Tiger,所以你只能使用属于ICanMove接口的扩展、方法或属性。
使用泛型方法可以通过轻微的签名更改提供各种可能性:
-
public void Method1<T>(class1 c, T obj) where T:Imyinterface, new()
:
这允许实例化类型为T的新实例。 -
public T Method1<T>(class1 c, T obj) where T:Imyinterface
:
这允许您在需要时使用该方法而不强制转换其返回值。 -
public void Method1<T>(class1 c, ref T obj) where T:Imyinterface
:
这允许您向obj
的引用传递一个新值。同样适用于out
。
这些对于非通用版本是不可能的。
在您的场景中,它实际上是相同的(除了使用接受接口参数的方法将具体对象上推为接口类型),请考虑稍微不同的场景。假设我们希望我们的方法只接受实现IMyInterface1
和IMyInterface2
两个接口的类,否则代码不应该编译:
interface IMyInterface1 { }
interface IMyInterface2 { }
class MyClass : IMyInterface1 { }
public void Method1<T>(Class1 c, T obj) where T : IMyInterface1, IMyInterface2
{
}
如果我们创建的方法接受interface作为它的第二个参数,它将不满足条件,因为它不限制用户发送只实现一个接口的类实例,但不像这个例子中MyClass和IMyInterface2那样实现第二个接口。
用户应该发送什么界面?他并不真正知道需要在编译时发送的类型。
这是使用泛型和泛型约束的好地方,另一方面,我们不能使用单个接口参数
void
方法之间差异不大
public void Method1<T>(class1 c, T obj) where T : Imyinterface
=
public void Method2(class1 c, Imyinterface obj, Type t)
其中t
必须为Imyinterface
。
所以如果你需要传递一些Type
给你的方法,你需要在编译时对Type
应用一些约束,使用泛型方法。