你所不知道的linq(二)

上一篇说了from in select的本质,具体参见你所不知道的linq。本篇说下from...in... from... in... select

首先上一段代码,猜猜结果是什么?

    class Program
    {
        static void Main(string[] args)
        {
            /*var result = from s in new TestApp() { A = 2 } select s;*/
            var result1 = from s in new TestApp() { A = 2 }
                          from i in (s + 2).ToString()
                          select (Convert.ToInt32(i) + s).ToString();

            Console.WriteLine(result1.GetType() + " " + result1);
            Console.ReadLine();
        }
    }

    public class TestApp
    {
        public int A { get; set; }
    }

这段代码的运行结果是什么呢?

 

 

答案是,这段代码会报错,根本编译不过~~~~~~那么按照上一篇,我们对TestApp进行方法扩展呢?那扩展Select扩展方法,发现依旧编译不过。最后查linq的api,发现了一个叫SelectMany的方法。在结合SelectMany的用法我们可以猜测应该是这个扩展方法。于是我对TestApp进行了如下扩展,

public static class SelectExtension
    {
        public static string Select(this TestApp app, Func<int, int> selector)
        {
            return "hello,你是" + selector(app.A).ToString();
        }
        public static string SelectMany(this TestApp app, Func<int, string> fun1, Func<int, string, string> fun2)
        {
            var j = fun1(app.A);
            return "hello,你真是" + fun2(app.A, j);
        }
    }

编译,运行,结果如下:

那么最后我们需要猜测SelectMany的通用方法是什么,也就是SelectMany到底是怎么定义的呢?

public static T SelectMany<T1,T2,T3,T>(this TestApp app, Func<T1, T2> fun1, Func<T1, T2, T3> fun2){}

其对应的from...in... from... in...select 语句如下

  from t1 in TestApp

  from t2 in fun1(t1)

  select fun2(t1,t2)

  • 对于需要扩展的类型也就是TestApp,位于第一个in后面
  • t1,类型为T1的,它是fun1和func2的参数,具体t1是什么,需要看SelectMany里面如何实现
  • t2,类型是T2的,它是通过fun1执行出来的,并且作为fun2的参数,不t2可能与t1没有直接关系,这个看fun1如何定义
  • 需要注意的是select后面的对象只是fun2的返回值,不是from...in... from... in...select语句的返回值,该语句的返回值是SelectMany扩展方法的返回值。

经过验证发现推论是那么完美,只要扩展SelectMany方法,代码完美运行。

不过悲剧也发生了,from...in... from... in... from... in... select,三重循环该如何重载呢还是SelectMany方法吗?我完全找不到北了,编译不成功,扩展失败,这是一个悲剧,希望知道的人告诉我结果~~~~~~~

posted @ 2016-12-12 10:13  [水&月]坟  阅读(633)  评论(0编辑  收藏  举报