Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit Type Inference only for lambda expressions ? Why ? Confused !

I have the following sample code (used for C# 3.5 study purpose only !).

I am making a call to the Sort function that accepts an IEnumerable and a sort function. If I call it using a lambda expression (Case A) the compiler can derive the return type TResult, however when I pass the func SortInt (Case B) the compiler throws an error !

I am unable to understand why the compiler cannot derive TResult in the second case ! I seem to be passing exactly the same information. Or is that not accurate ?

Please Help !

int[] intArray = { 1, 3, 2, 5, 1 };

IEnumerable<int> intArray2 = Sort(intArray, x => SortInt(x)); // <= CASE A - OK !

IEnumerable<int> nextIntArray = Sort(intArray, SortInt); // <= CASE B - Compile Error: Cannot Infer Type !

public static IEnumerable<TResult> Sort<T, TResult>(IEnumerable<T> toBeSorted,    
                              Func<IEnumerable<T>, IEnumerable<TResult>> sortFunc)
{
    return sortFunc(toBeSorted);
}

public static IEnumerable<int> SortInt(IEnumerable<int> array)
{
    return array.OrderByDescending(x => x);
}
like image 276
Preets Avatar asked Dec 08 '22 05:12

Preets


2 Answers

It appears as if the inference fails on your second example because the compiler cannot perform overload resolution on SortInt.

This may be useful as a more thorough explanation:

http://blogs.msdn.com/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx

like image 113
Robert Venables Avatar answered Mar 16 '23 19:03

Robert Venables


I agree that it's annoying that type inference doesn't work well for method group conversions. I would like the C# compiler to be smarter in the common case where there's only one applicable method in the group. In complex situations, however, you can end up with multiple applicable overloads which would lead to different types being inferred.

Options:

  • Call the method from a lambda expression, as you've shown
  • Specify the type arguments explicitly instead of relying on inference
  • Cast the method group to the specific type involved (worse than the second option)
  • Use a separate local variable and specify its type explicitly

Basically I would stick with either of the first two options, annoying as they both are. Note that there'll be a slight performance loss with the first option as it's an extra level of indirection, but that usually won't be significant.

like image 35
Jon Skeet Avatar answered Mar 16 '23 20:03

Jon Skeet