深入Linq查询运算符

回顾
   前面我们说过LINQ查询表达式只能操作实现了IEnumerable接口的对象。
   再来看前面几个例子,我们通过数组来使用了LINQ查询表达式,那是否Array实现了IEnumerable接口了?
   可以看到正式的Array定义如下:
     //Array类型看上去并没有实现查询表达式所需要的接口
     public abstract class Array:ICloneable,IList,ICollection,IEnumerable
     {....}
     然而你通过数组的实例来点  可以点出很多原本在Array里并没有提供的方法。
     想想你可能马上就想到了扩展方法,对,是其他类型在幕后对Array类型做了扩展,所以我们才可以得到那些功能.
  
目标:

    1.Linq查询表达式内部实现机制
    2.Linq查询运算符的演变过程


一、LINQ查询表达式内部实现机制:
LINQ可以操作数组类型,也可以操作System.Collections.Generic命名空间的成员类型如:List
使用LINQ查询非泛型的集合
System.Enumerable类型提供很多对IEnumerable接口的扩展方法
ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication4
ExpandedBlockStart.gifContractedBlock.gif
{
    
class Test1
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            ArrayList list 
= new ArrayList();
            list.Add(
"Asp.net");
            list.Add(
111);
            list.Add(
"Ajax");
            
//通过扩展方法OfType把ArrayList转换成了一个兼容于IEnumber的类型
            IEnumerable<string> myList=list.OfType<string>();
            var item 
= from g in myList
                       
where g.Length > 5
                       orderby g
                       select g;
ExpandedSubBlockStart.gifContractedSubBlock.gif            Array.ForEach
<string>(item.ToArray<string>(), s => { Console.WriteLine(s); });
                   
        }

    }

}

//注意非泛型类型可以包含任何类型的项,以ArrayList为例,它接受的是Object类型的项
//使用OfType可以过滤出类型不满足T的类型的项

正式的System.Linq.Enumerable的定义如下:
ContractedBlock.gif ExpandedBlockStart.gif Code Enumerable的定义
namespace System.Linq
ExpandedBlockStart.gifContractedBlock.gif
{
    
//这个类型扩展了很多早先2.0里类型没有的方法     这些都是底层的实现
    public static class Enumerable
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
//扩展了IEnumerable接口,相当于在IEnumerable接口里添加了一个OfType的泛型方法
        public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if (source == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
throw Error.ArgumentNull("source");
            }

            
return OfTypeIterator<TResult>(source);
        }

        
//扩展了IEnumerable接口  其接受一个参数并返回一个bool类型的委托
        public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if (source == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
throw Error.ArgumentNull("source");
            }

            
if (predicate == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
throw Error.ArgumentNull("predicate");
            }

            
return WhereIterator<TSource>(source, predicate);
        }

     
    }

}

二、Linq查询运算符的演变过程
ContractedBlock.gifExpandedBlockStart.gifCode
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication4
ExpandedBlockStart.gifContractedBlock.gif
{
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//***********************************************************************************************************
    Func委托                         封装一个不具有参数但却返回 TResult 参数指定的类型值的方法。
    Func委托                       封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。
    Func委托                     封装一个具有二个参数并返回 TResult 参数指定的类型值的方法。
    Func委托                   封装一个具有三个参数并返回 TResult 参数指定的类型值的方法。
    Func委托                 封装一个具有四个参数并返回 TResult 参数指定的类型值的方法。
    
LINQ查询运算符的演变过程
***********************************************************************************************************
*/

    
class TestApp
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
ExpandedSubBlockStart.gifContractedSubBlock.gif            var s 
= new[] "Hello Word!""Study Hard""Asp.net 3.0"".NET FrameWork3.5" };//集合初始化器构建一个隐式数组
            Console.WriteLine("第一种方式:");
            
//使用System.Enumerable类型里的扩展方法和原始代理建立查询表达式
            Func<stringbool> filter = new Func<stringbool>(Fileter);
            Func
<stringstring> itemToProcess = new Func<stringstring>(ProcessItem);
            var list1 
= s.Where(filter).OrderBy(itemToProcess).Select(itemToProcess);//实例调用扩展方法
ExpandedSubBlockStart.gifContractedSubBlock.gif
            Array.ForEach<string>(list1.ToArray<string>(), g => { Console.WriteLine(g); });

            Console.WriteLine(
"第二种方式:");
            
//使用System.Enumerable类型里的扩展方法和匿名方法来建立查询表达式
            Func<stringbool> searchFilter = delegate(string g)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return g.Length > 15;
            }
;
            Func
<stringstring> item = delegate(string g)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return g;
            }
;
            var list2 
= Enumerable.Where(s, searchFilter).OrderBy(item).Select(item);//静态调用扩展方法
ExpandedSubBlockStart.gifContractedSubBlock.gif
            Array.ForEach<string>(list2.ToArray<string>(), g => { Console.WriteLine(g); });

            
//使用lambda表达式来建立查询表达式
            Console.WriteLine("第三种方式:");
            var list3 
= s.Where(g => g.Length > 15).OrderBy(g => g).Select(g => g);//通过Lambda表达式建立查询表达式  把匿名方法都代替成Lambda表达式
ExpandedSubBlockStart.gifContractedSubBlock.gif
            Array.ForEach<string>(list3.ToArray<string>(), g => { Console.WriteLine(g); });
           
           Console.WriteLine(
"第四种方式:");
           var list4 
= from g in s where g.Length > 15 orderby g select g;  //哇!LINQ查询表达式就1行代码就完成了上面所做的工作
ExpandedSubBlockStart.gifContractedSubBlock.gif
           Array.ForEach<string>(list4.ToArray<string>(), g => { Console.WriteLine(g); });
           
//其实新的语法就是简化了调用Enumerable类型定义的扩展方法的简化符号
        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
static bool Fileter(string s) return s.Length > 15; }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
static string ProcessItem(string s) return s; }
    }

}


总结:
    查询表达式是用各种查询运算符建立的
    查询运算符只是调用了由System.linq命名空间下的Enumerable定义的扩展方法的简化符号
    Enumerable的许多方法都要求代理(特别是Func<>)作为参数
    在C#3.0  任何要求代理参数的方法都可以传入一个Lambda表达式
     Lambda是伪造的匿名方法
     匿名方法是对指派一个原始代理然后手工建立一个代理目标方法的简化符号.

转载于:https://www.cnblogs.com/huangting2009/archive/2009/05/15/1457193.html

你可能感兴趣的:(c#)