Constraint vs Parameter - forced collection method as a parameter

I am wondering if there is a difference between the two methods. The second is more natural, but this is not the only reason for using it. Maybe there are some performance issues or some kind of diabolical mamboyambo related to any of them?

void FirstMethod<T>(T a) where T : IEnumerable<Animal> { ... } void SecondMethod<T>(IEnumerable<T> a) where T : Animal { ... } 
+6
source share
2 answers

The difference is that you can easily pass an IEnumerable<Dog> to the second method, but when you pass it to the first method, it will just be implicitly converted to IEnumerable<Animal>

Take a look at fiddle

Edited Thanks @Servy for the comment.

+6
source

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(); } 

Looking at the generated IL code, there is no difference between the two method calls, and both of them accept cats as a parameter.

Edit: differences occur in the methods as shown below. (thanks @servy for the comment)

 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 

The use of a decompiler in this IL code indicates where boxing occurs for 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); } 
0
source

Source: https://habr.com/ru/post/978285/


All Articles