约束与参数 - 强制收集为参数的方法
本文关键字:参数 方法 约束 | 更新日期: 2023-09-27 18:30:36
我想知道这两种方法之间是否有任何区别。第二个看起来更自然,但这不应该是使用它的唯一原因。也许有一些性能问题或一些恶魔般的曼波詹博与其中任何一个有关?
void FirstMethod<T>(T a) where T : IEnumerable<Animal>
{
...
}
void SecondMethod<T>(IEnumerable<T> a) where T : Animal
{
...
}
不同之处在于您可以轻松地将IEnumerable<Dog>
传递给第二种方法,但是当你把它传递给第一种方法时,它只会隐式转换为IEnumerable<Animal>
看看小提琴
已编辑 感谢@Servy的评论。
我在 LinqPad 中尝试了此示例:
void Main()
{
var cats = new [] { new Cat() };
FirstMethod(cats);
SecondMethod(cats);
}
interface Animal
{
}
class Cat : Animal
{
}
void FirstMethod<T>(T a) where T : IEnumerable<Animal>
{
var b = a.FirstOrDefault();
}
void SecondMethod<T>(IEnumerable<T> a) where T : Animal
{
var b = a.FirstOrDefault();
}
通过查看生成的 IL 代码,对方法的 2 个调用之间没有区别,它们都接受cats
作为参数。
编辑:差异发生在方法中,如下所示。(谢谢@servy的发言)
IL_001D: ldarg.0
IL_001E: ldloc.0 // cats
IL_001F: call UserQuery.FirstMethod
IL_0024: nop
IL_0025: ldarg.0
IL_0026: ldloc.0 // cats
IL_0027: call UserQuery.SecondMethod
FirstMethod:
IL_0000: nop
IL_0001: ldarg.1
IL_0002: box 02 00 00 1B
IL_0007: call System.Linq.Enumerable.FirstOrDefault
IL_000C: stloc.0 // b
IL_000D: ret
SecondMethod:
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call 05 00 00 2B
IL_0007: stloc.0 // b
IL_0008: ret
在此 IL 代码上使用反编译器会显示装箱发生的位置,以确保类型安全。
private void Main()
{
Cat[] a = new Cat[1]
{
new Cat()
};
this.FirstMethod<Cat[]>(a);
this.SecondMethod<Cat>((IEnumerable<Cat>) a);
}
private void FirstMethod<T>(T a) where T : IEnumerable<Animal>
{
Enumerable.FirstOrDefault<Animal>((IEnumerable<Animal>) a);
}
private void SecondMethod<T>(IEnumerable<T> a) where T : Animal
{
Enumerable.FirstOrDefault<T>(a);
}