Reputation: 629
I am wondering if there is any difference between these two methods. Second one look more natural, but that shouldn't be the only reason to use it. Maybe there are some performance issues or some diabolic mambojambo related to any of them?
void FirstMethod<T>(T a) where T : IEnumerable<Animal>
{
...
}
void SecondMethod<T>(IEnumerable<T> a) where T : Animal
{
...
}
Upvotes: 6
Views: 223
Reputation: 582
I tried this sample in 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();
}
By looking at the IL code generated, there is no difference between the 2 call to methods and they both accept cats
as parameter.
Edit: the differences occur IN the methods as seen below. (thank you @servy for the remark)
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
Using a decompiler on this IL code shows where the boxing occurs to ensure type safety.
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);
}
Upvotes: 0
Reputation: 3938
The difference is that you can easily pass IEnumerable<Dog>
to the second method,
but when you pass it to the first method it'll just be implicitly converted to an IEnumerable<Animal>
Take a look at the fiddle
Edited Thanks @Servy for comment.
Upvotes: 6