javalambdaorderby_关于Linq中的Lambda表达式中OrderBy
的深⼊理解
起因:就是⼀段Linq语句,OrderBy⾥⾯的i是什么?
IQueryable slist = (from s in EFDB.Student selects).
OrderBy(i=> i.Name).Skip((2 - 1) * 3).Take(3);
说来也奇怪,同样是形参s就能理解,就是数据集合。 那OrderBy⾥⾯的i是什么?
直接上源码吧
[__DynamicallyInvokable]public static IOrderedQueryable OrderBy(this IQueryable source, Expression>keySelector)
{if (source == null)
{throw Error.ArgumentNull("source");
}if (keySelector == null)
{throw Error.ArgumentNull("keySelector");
}return (IOrderedQueryable) source.Provider.CreateQuery(Expression.Call(null, ((MethodInfo)
MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource), typeof(TKey) }), newExpression[] { source.Expression, Expression.Quote(keySelector) }));
}
这⾥是⼀个扩展⽅法,扩展的是 IQueryable 类,
这个⽅法关键看最后⼀句话,返回⼀个CreateQuery⽅法,看⼀下它的源码
[__DynamicallyInvokable]
IQueryable CreateQuery(Expression expression);
IL代码(这个参考,不⽤在意)
.method public hidebysig newslot abstract virtual instance class
System.Linq.IQueryable`1CreateQuery(classSystem.Linq.Expressions.Expression expression) cil managed
{
.custom instancevoid__DynamicallyInvokableAttribute::.ctor()
}
那么下⾯这个就相当于CreateQuery⽅法的Expression 参数
Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource), typeof(TKey) }), newExpression[] { source.Expression, Expression.Quote(keySelector) })
那么再进⼀步看看Call⽅法,这个⽅法就是返回的Expression参数
[__DynamicallyInvokable]public static MethodCallExpression Call(Expression instance, MethodInfo method, paramsExpression[] arguments)
{return Call(instance, method, (IEnumerable) arguments);
}
再进⼀步看Call
[__DynamicallyInvokable]public static MethodCallExpression Call(Expression instance, MethodInfo method, IEnumerablearguments)
{
ContractUtils.RequiresNotNull(method,"method");
ReadOnlyCollection onlys = arguments.ToReadOnly();
ValidateMethodInfo(method);
ValidateStaticOrInstanceMethod(instance, method);
ValidateArgumentTypes(method, ExpressionType.Call,refonlys);if (instance == null) //现在instance就是等于null
{return newMethodCallExpressionN(method, onlys);
}return newInstanceMethodCallExpressionN(method, instance, onlys);
lambda编程}
继续看MethodCallExpressionN⽅法
public MethodCallExpressionN(MethodInfo method, IList args) : base(method)
{this._arguments =args;
}
看到这⾥,我们就可以反推回去,Call⽅法最后就是把arguments(IEnumerable集合)返回给CreateQuery,⽽这个arguments形参就是CreateQuery的
new Expression[] { source.Expression, Expression.Quote(keySelector) }
再看看这⾥的Quote⽅法
[__DynamicallyInvokable]public staticUnaryExpression Quote(Expression expression)
{
RequiresCanRead(expression,"expression");if (!(expression isLambdaExpression)) //如果不是lambda表达式,则抛异常
{throwError.QuotedExpressionMustBeLambda();
}return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null); //
}
看到这⾥,终于知道原来
public static IOrderedQueryable OrderBy(this IQueryable source, Expression> keySelector)
可以理解为
public static IOrderedQueryable OrderBy(LambdaExpression )
⾄此,终于明⽩开头这句话的
(from s in EFDB.Student selects)
.OrderBy(i=> i.Name)
.Skip((2 - 1) * 3)
.Take(3);
OrderBy⾥⾯的i是取决于之前是谁调⽤的这个⽅法
上⾯source代表实体集,source.Expression代表实体集中的每⼀个实体。=>也就是说lambda表达式中的形参i,代表⼀个实体,⽽不是实体集。
个⼈推测,Linq中OrderBy、Where都是返回的按照各⾃method、筛选器之后的集合,泛型委托。这种写法有点像链式编程。
完毕!
如有不正确的地⽅,请不吝赐教。
感谢我的⼏位好友:时同学、邵同学、倪同学、黄同学等对我⼀直以来的帮助。
因为我们都知道⼀个道理:单则易折、众则难摧。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论