0

Looking for a solution to an issue, I found the following code:

public interface IOrderExpression<TEntity>
{
    OrderDirection Direction { get; set; }
    LambdaExpression Selector { get; }
}

public static IQueryable<T> GetOrder<T>(this IQueryable<T> queryable, IList<IOrderExpression<T>> orderExpressions)
{
    var firstOrderExpression = orderExpressions.First();

    queryable = firstOrderExpression.Direction == OrderDirection.Ascending
        ? Queryable.OrderBy(queryable, firstOrderExpression.Selector as dynamic)
        : Queryable.OrderByDescending(queryable, firstOrderExpression.Selector as dynamic);

    [..]
}

At the first read, I thought:

this code can't compile, there is no OrderBy function in the Queryable class that match a dynamic parameter.

But this code was marked as answer so I wrote it in my IDE to be sure. I wrote it this way: queryable.OrderBy(firstOrderExpression.Selector as dynamic) and it does not compile as expected:

'IQueryable' does not contain a definiion for 'OrderBy' and the best extensions method overload 'Queryable.OrderBy' requires a receiver of type 'IQueryable'

But then, I wrote it exactly as I found it (using Queryable.OrderBy([..]) and it actually compiles (AND works at runtime!). This troubles me even more since I thought these two ways to call an extension method were identical...

Can someone explain me why this is allowed by the compiler?

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
fharreau
  • 2,105
  • 1
  • 23
  • 46
  • 1
    Use of `dynamic` types and extension methods do not mix. – Jeff Mercado Jan 17 '20 at 00:51
  • The duplicate explains why the first attempt does _not_ compile. As to why the second one does, it's because `dynamic` defers all binding until runtime, so it bpyasses the compiler and gets bound at run-time. Luckily, the value you pass in matches what the method will accept so it gets bound properly at runtime. – D Stanley Jan 17 '20 at 00:54

1 Answers1

0

The 2nd parameter here falls into the overload accepting an key selector. The compiler discards that information.

OrderBy is an extension of IQueryable<T> and there's no way in the compiler to safely get that type information for the runtime.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445