官方QQ群:127876820【C#编程技术-全国站--未满人】

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 = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
//查询数组中元素值大于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

            }

 

posted @ 2010-10-09 18:32  碧海蓝天_C#  阅读(643)  评论(0编辑  收藏  举报
官方QQ群:127876820【C#编程技术-全国站--未满人】