zoukankan      html  css  js  c++  java
  • 关于Linq中的Lambda表达式中OrderBy的深入理解

    起因:就是一段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、筛选器之后的集合,泛型委托。这种写法有点像链式编程。

     

    完毕!

    如有不正确的地方,请不吝赐教。

    感谢我的几位好友:时同学、邵同学、倪同学、黄同学等对我一直以来的帮助。

    因为我们都知道一个道理:单则易折、众则难摧。

         

  • 相关阅读:
    第十二周作业
    第九周作业
    第八周作业
    第七周作业
    第六周作业
    参考博文地址
    第五周作业
    用例设计思路
    测试方法的四大金刚
    网络模型及访问过程
  • 原文地址:https://www.cnblogs.com/John-Marnoon/p/6038937.html
Copyright © 2011-2022 走看看