哼哼, LINQ!

    习惯了用LINQ的人一定用的很爽, 整天LINQ来LINQ去的, LINQ确实是很好的东西, 简洁, 方便, 最重要的是统一了数据的查询方式, 使得程序员不必关心数据的出处(绝对不关心数据的出处是不可能的, 但至少统一了查询方式, 统一了"项目接口"), 这一点对软件工程很有意义.

    不过...........它是如何实现的呢?...................

    恩, 又是语法糖, 不这回是个超级大语法糖, 外带一些类库糖.

    如果把整个LINQ比作一个人,那我们先来写一个麻雀:

     // 定义委托类型。
     public   delegate  T TheFun < T > ();

    
// 定义一个接口。
     public   interface  IHaveCount
    {
        
int  MyCount1 {  get set ; }
        
int  MyCount2 {  get set ; }
    }

    
// 这是类库糖
     public   static   class  HaveCountOperations
    {
        
// 使用扩展方法这个语法糖。
         public   static  IHaveCount AddCount2ToCount1( this  IHaveCount haveCount, TheFun < bool >  ifDoOrNot)
        {
            
// 执行委托,用来判断是否执行。
             if  (ifDoOrNot.Invoke())
            {
                haveCount.MyCount1 
+=  haveCount.MyCount2;
            }
            
return  haveCount;
        }
    }

    
// 定义一个类
     public   class  A : IHaveCount
    {
        
public   string  Name;

        
#region  IHaveCount Members
        
public   int  MyCount1 {  get set ; }
        
public   int  MyCount2 {  get set ; }
        
#endregion
    }


    然后调用它:

            A a  =   new  A { MyCount1  =   100 , MyCount2  =   2  };
            a.AddCount2ToCount1(() 
=>   true ).AddCount2ToCount1(()  =>   true ).AddCount2ToCount1(()  =>   false );

            Console.WriteLine(a.MyCount1.ToString());

    结果为104。

    
    我们回过头来看一下,不难发现在这个麻雀结构中最关键的就是类库糖中针对接口IHaveCount的扩展方法,麻雀虽小,但很能反映问题。LINQ中,最本质的也是这样一种设计思路。伟大的LINQ设计师当初就要面对这样一种场景:如何针对不同的载体类型,统一数据集的查询方式?

    绝不可能去重写所有的载体类型比如List、Array,但这些集合类型都实现了同样的一个接口:IEnumerable<T>,也就是说都是可以使用迭代器查看数据集中的每一个数据的,只要能把查询条件以某种方式传到foreach结构中,然后再返回符合条件的同样继承IEnumerable<T>的集合不就可以设计出类似sql的查询语言?查询条件可以使用委托,下一个问题是如何返回集合,当然可以新new一个,不过聪明的LINQ设计师却使用了yield return,呵,这样一来,不仅减少了代码量,还顺便实现了延迟加载的特性。这样一来,核心设计便没有问题了,可是使用起来却比较难看,于是有了扩展方法,让类库糖调用起来像实例方法一样方便,于是又产生了匿名委托,匿名方法等等等等,可以说C# 3.0绝大部分新特性都被用在了LINQ上。再结合泛型方法,泛型委托,LINQ看起来竟显得如此漂亮。

     如果把整个LINQ比作一个人,那我们最后再来写一条狗:(编译完了强烈建议大家用Reflector反编译仔细研究研究)

     public   static   class  LINQDogOperations
    {
        
public   static  IEnumerable < TResult >  LittleDogSelect < TSource, TResult > ( this  IEnumerable < TSource >  source, Func < TSource, TResult >  selector)
        {
            
foreach  (TSource ts  in  source)
            {
                
yield   return  selector(ts);
            }
        }

        
public   static  IEnumerable < TSource >  LittleDogWhere < TSource > ( this  IEnumerable < TSource >  source, Func < TSource,  bool >  predicate)
        {
            
foreach  (TSource ts  in  source)
            {
                
if  (predicate(ts))
                {
                    
yield   return  ts;
                }
            }
        }


随便调用试试:

     class  Program
    {
        
static   void  Main( string [] args)
        {
            List
< TestClass >  test  =   new  List < TestClass > ();

            
for  ( int  i  =   0 ; i  <   1000 ; i ++ )
            {
                test.Add(
new  TestClass { ID  =  i, Password  =  i.ToString() });
            }

            var v1 
=  test.LittleDogSelect((i)  =>   new  { i.ID, i.Password }).LittleDogWhere((c)  =>  c.ID  >   500 );

            Console.WriteLine(v1.Count().ToString());
        }
    }


    
public   class  TestClass
    {
        
public   int  ID;
        
public   string  Password;
        
public   int  State;
    }

    呵呵,当一切语法糖条件具备,看吧,就那几行代码,感谢万能的编译器。感谢聪明的设计师。

你可能感兴趣的:(LINQ)