LINQ 和泛型

      在.net2.0中引用了泛型,泛型是我在.net 2.0众多特性中最喜欢的一个,可以说泛型给我们的编程思想上带来了不小的影响。.net2.0和.net1.1相比,很多功能用泛型和不用泛型都可以实现,例如过滤一个数组元素。但使用泛型会带来很多额外的好处,或者说泛型能办很多非泛型时代不能完成的任务。


      案例一:对增删改查用面向对象进行包装,如果想把客户端与业务处理以及数据处理部分更好的解耦,如果在.net1.1时代是很难实现的。像很多开源的框架,都有强大的ORM编程模式,它使得所有的增删改查都最终统一表现在接口方法上,接受的参数正是实体对象而不依赖于具体的数据源类型。


      案例二:IComparer<T>接口的扩展,IComparer<T>接口对于实体集的排序提供了非常灵活的方案,比起IComparer接口,省去了烦人的类型转换以及类型安全问题。我们还可以对IComparer<T>接口进行更进一步的封装,让它在客户端更加解耦,可以参数这篇文章:泛型真的很神奇


      案例三:对于数组或者是实体集的查询,说的直接点就是实现了IEnumerable,IEnumerable<T>或派生类型,如 IQueryable<T>接口的集合。传统的IEnumerable接口在查询数据时都需要用到foreach操作,而泛型IEnumerable接口或派生类型,如 IQueryable<T>接口,提供了更加简单而且更加高效安全的查询模式。

      示例:下面一个简单的示例来说明下LINQ中的泛型应用。
            

//申明一个整形数组
int[] num = { 012345678 };
//查询数组中元素值大于1的集合
//传统方式
            ArrayList listArr = new ArrayList();
            
foreach (int i in num)
            {
                
if (i < 1)
                {
                    listArr.Add(i);
                }
            }
//LINQ方式
            
//匿名类型方式
            var list = from _num in num
                       
where _num > 1
                       select _num;

 

        非泛型方式的缺点:
          1):从代码量来看,比LINQ方式多;
          2):ArrayList相对泛型在性能上具有先天上的劣势。
          3):LINQ充分利用了泛型的优点再结合LINQ优良的查询方式,使得代码的可阅读性进一步加强。  

       下面是我结合MSDN总结的一些LINQ中的泛型部分用法,不足处忘指正。  
            
       第一:LINQ查询中的IEnumerable<T>变量。下面代码中显示类型方式中IEnumerable<int>,就表明查询出来的集体里面都只会存放0个或者n个整形类型的数据。

//显示类型方式
IEnumerable<int> list2 = from _num in num
                                     
where _num > 1
                                     select _num;

 

       第二:系统推断变量类型。由于.net3.0推出了匿名类型,所以我们可以把IEnumerable<int>直接写成var,让系统去判断变量的类型。
      

//匿名类型方式
var list = from _num in num
                       
where _num > 1
                       select _num;


       第三:查询操作中的类型关系,第二条中我们知道可以引用匿名类型来让系统来判断变量的类型,但要写出有效的查询,我们最好了解对象之间的关联关系。LINQ 查询操作在数据源、查询本身及查询执行中是强类型的。查询中变量的类型必须与数据源中元素的类型和 foreach 语句中迭代变量的类型兼容。


        1):查询操作中不需要转换数据源。查询的结果集元素类型和数据源元素类型相同。第一条中的显示类型方式查询中,记录集元素类型为IEnumerable<int>,如果我们要对集合做foreach操作,我们需要这样写:

        

            foreach (int i in list2)
            {
                
//dosomething
            }
            
foreach (var  i in list2)
            {
                
//dosomething
            }


        2):查询操作中需要类型转换。如果原始数据源和最后查询数据源的元素类型不同,说明需要类型转换,下面是一个学生类的集合,但我们只需要返回满足条件的学生的电话号码并不需要其它信息,这里为了查询的有效性,并不需要满足条件学生的所有信息,即不需要返回整个student,这相当是SQL中的select *。下面是一个学生类:

/// <summary>
    
/// 学生实体
    
/// </summary>
    class student
    {
        
/// <summary>
        
/// 姓
        
/// </summary>
        public string sFirst
        {
            
get;
            
set;
        }
        
/// <summary>
        
/// 名
        
/// </summary>
        public string sLast
        {
            
get;
            
set;
        }
        
/// <summary>
        
/// 电话
        
/// </summary>
        public string sPhone
        {
            
get;
            
set;
        }
    }

   

          构造学生数据源      

//学生姓名电话集合
            IEnumerable<student> listStudent = new List<student> {
                                                  
new student {sFirst = "",sLast ="",sPhone ="1111111"},
                                                  
new student {sFirst ="",sLast ="",sPhone ="2222222"},
                                                  
new student {sFirst ="",sLast ="",sPhone ="3333333"}
            };

           

           查询姓李的学生的电话号码.

IEnumerable<string> listStudentQuery = from item in listStudent
                                  
where item.sFirst == ""
                                  select item.sPhone;

 

           猜测: 如果原始数据源实现了IEnumerable或者是IEnumerable<T>,那么查询出来的结果集也会实现数据源的接口。这里没有找到相关资料,有的朋友方便给出下。所以类型为IEnumerable<student>的数据源,得到的查询结果也会实现IEnumerable<T>接口。

           错误查询:
            

IQueryable <string> listStudentQuery2 = from item in listStudent
                                                   
where item.sFirst == ""
                                                   select item.sPhone;

 

           3):让系统完全代理数据类型推断操作。即查询时我们不显示指定数据类型。查询姓李的学生的电话号码
            

var  listStudentQuery2 = from item in listStudent
                                                   
where item.sFirst == ""
                                                   select item.sPhone;
            
foreach (var  s in listStudentQuery2)
            {
                
//dosomething

            }

     

 注:本文参考MSDN

posted on 2009-05-17 17:05  min.jiang  阅读(6868)  评论(12编辑  收藏  举报