起因:就是一段Linq語句,OrderBy里面的i是什么?
IQueryable<Student> slist = (from s in EFDB.Student select s). OrderBy(i => i.Name).Skip((2 - 1) * 3).Take(3);
說來也奇怪,同樣是形參s就能理解,就是數據集合。 那OrderBy里面的i是什么?
直接上源碼吧
[__DynamicallyInvokable] public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector) { if (source == null) { throw Error.ArgumentNull("source"); } if (keySelector == null) { throw Error.ArgumentNull("keySelector"); } return (IOrderedQueryable<TSource>) source.Provider.CreateQuery<TSource>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource), typeof(TKey) }), new Expression[] { source.Expression, Expression.Quote(keySelector) })); }
這里是一個擴展方法,擴展的是 IQueryable<TSource> 類,
這個方法關鍵看最后一句話,返回一個CreateQuery方法,看一下它的源碼
[__DynamicallyInvokable] IQueryable<TElement> CreateQuery<TElement>(Expression expression);
IL代碼(這個參考,不用在意)
.method public hidebysig newslot abstract virtual instance class System.Linq.IQueryable`1<!!TElement> CreateQuery<TElement>(class System.Linq.Expressions.Expression expression) cil managed { .custom instance void __DynamicallyInvokableAttribute::.ctor() }
那么下面這個就相當於CreateQuery方法的Expression 參數
Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource), typeof(TKey) }), new Expression[] { source.Expression, Expression.Quote(keySelector) })
那么再進一步看看Call方法,這個方法就是返回的Expression 參數
[__DynamicallyInvokable] public static MethodCallExpression Call(Expression instance, MethodInfo method, params Expression[] arguments) { return Call(instance, method, (IEnumerable<Expression>) arguments); }
再進一步看Call
[__DynamicallyInvokable] public static MethodCallExpression Call(Expression instance, MethodInfo method, IEnumerable<Expression> arguments) { ContractUtils.RequiresNotNull(method, "method"); ReadOnlyCollection<Expression> onlys = arguments.ToReadOnly<Expression>(); ValidateMethodInfo(method); ValidateStaticOrInstanceMethod(instance, method); ValidateArgumentTypes(method, ExpressionType.Call, ref onlys); if (instance == null) //現在instance就是等於null { return new MethodCallExpressionN(method, onlys); } return new InstanceMethodCallExpressionN(method, instance, onlys); }
繼續看MethodCallExpressionN方法
public MethodCallExpressionN(MethodInfo method, IList<Expression> args) : base(method) { this._arguments = args; }
看到這里,我們就可以反推回去,Call方法最后就是把arguments(IEnumerable<Expression>集合)返回給CreateQuery,而這個arguments形參就是CreateQuery的
new Expression[] { source.Expression, Expression.Quote(keySelector) }
再看看這里的Quote方法
[__DynamicallyInvokable] public static UnaryExpression Quote(Expression expression) { RequiresCanRead(expression, "expression"); if (!(expression is LambdaExpression)) //如果不是lambda表達式,則拋異常 { throw Error.QuotedExpressionMustBeLambda(); } return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null); // }
看到這里,終於知道原來
public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector)
可以理解為
public static IOrderedQueryable<TSource> OrderBy(LambdaExpression )
至此,終於明白開頭這句話的
(from s in EFDB.Student select s)
.OrderBy(i => i.Name)
.Skip((2 - 1) * 3)
.Take(3);
OrderBy里面的i是取決於之前是誰調用的這個方法

上面source代表實體集,source.Expression代表實體集中的每一個實體。=> 也就是說lambda表達式中的形參i,代表一個實體,而不是實體集。
個人推測,Linq中OrderBy、Where都是返回的按照各自method、篩選器之后的集合,泛型委托。這種寫法有點像鏈式編程。

完畢!
如有不正確的地方,請不吝賜教。
感謝我的幾位好友:時同學、邵同學、倪同學、黃同學等對我一直以來的幫助。
因為我們都知道一個道理:單則易折、眾則難摧。
