日期:2014-05-20  浏览次数:20826 次

LINQ学习心得分享----(一)LINQ简介和基础学习

     这一节主要向大家讲三个问题,第一个问题什么是LINQ,第二个问题LINQ主要解决什么问题,第三个问题学习LINQ需要做哪些基本的准备。

     首先第一个问题,什么是LINQLINQ中文翻译为语言集成查询(Language Integrated Query,更通俗的讲,它相当于一个通用的数据查询接口。LINQ最初由Anders hejlsberg构思,20071119日,LINQ作为.NET FrameWork3.5的一部分正式发布,同时微软也将LINQ集成到了Visual Studio 2008中,这一巨大的创新,实现了面向对象和数据访问的互通有无。

     第二个问题,LINQ主要解决什么问题?也就是LINQ的设计目的。我们知道在LINQ之前,面向对象和数据访问这两个领域是相互分裂的,编程语言中的数据类型,和数据库中的数据类型也有一些出入,同时SQLXML都有自己的查询语言而对象却没有自己的查询语言,这些在很大程度上限制开发的效率,而LINQ的设计理念就是在不同类型的数据之间(关系数据、层次模型数据等)之间实现数据访问的互通有无,为不同的数据类型提供统一的访问接口。具体体现为LINQ主要包含了以下三大部分: LINQ to Objects主要负责对象的查询,LINQ to XML 主要负责XML的查询, LINQ to ADO.NET主要负责数据库的查询,而LINQ to ADO.NET又包括 LINQ to SQL,LINQ to DataSet,LINQ to Entrties这三部分。这样就很好的符合了其设计理念,实现了对不同类型的数据访问。

     第三个问题,LINQ学习需要做哪些准备?也就是需要掌握哪些前期的基础知识。在开始学习LINQ之前,我们需要先来了解下理解C# 3.0的一些新特性:隐含类型局部变量、自动属性、对象初始化器、集合初始化器、匿名类型、Lambda表达式、扩展方法、局部方法、yield和IEnumerable接口、查询句法。

     下面我会通过做一些小例子,把这些特性一一给大家讲解一下。

      1、隐含类型的局部变量。

      学过Javascript的朋友相信对var这个关键字肯定一点也不陌生,我们都知道Javascript是一种弱类型的语言,所以在运行的时候才会更加的灵活。我们现在所接触的语言大部分都是强类型的语言,所谓强类型的语言,就是程序声明的变量、实例化对象,必须有明确的类型规定,这样在编译的时候就为其分配一定的内存空间,这样的话代码的安全的安全性就比较高,弱类型的语言比较灵活,但是它也比较容易出错也是其诟病之一。为了提高程序的运行效率和灵活性,微软也把var给引进了进来。看下面的例子:

private static void UnknowName()

        {

            var name = "Olive";

            var age = 22;

            var address = "北京";

            var Frieds = new[] { "Olive", "MoYao", "Momo" };

            Console.WriteLine("名字为:"+name);

            Console.WriteLine("年龄:" + age * 2);

            foreach (var f in Frieds)

            {

                Console.WriteLine(f);

            }

            Console.ReadKey();

        }

实验结果:

调试时,编译器自动识别数据类型:

运行结果:

由实验结果可知:编译器可以自动识别隐含类型的局部变量,但是前提是变量必须有值,但是在使用null之前,必须要确定类型,例如:var test=(string)null;这样编译器可以自动的推断值类型,如果单纯的为test=null,则编译器无法识别其类型

2、自动属性

直接看下面代码:

C#3.0以前创建一个类:

Class Person{

      private string name;

        private string sex;

        private int age;

        public string Name

        {

            get{ return name; }

            set{name = value;}

        }

        public string Sex

        {

            get { return sex;}

            set { sex = value;}

        }

        public int Age

        {

            get{ return age;}

            set{ age = value;}

        }

}

C#3.0以后可以这样写,相当于一个语法糖,省了很多代码,效果是一样的。

public class Person

    {

        public string Name

        {

            get;

            set;

        }

        public string Sex

        {

            get;

            set;

        }

        public int Age

{

            get;

            set;

            }      

    }

3、对象初始化器

在这里还是用上边的例子,在C#3.0以前可以这样初始化对象

Person p=new Person();

p.Name="Olive";

p.Sex="";

p.Age=22;

C#3.0以后可以这样初始化

Person p=new Person(){ Name="Olive",Sex="",Age=22};

4、集合初始化器

还是上边的例子:

C#3.0之前

List<Person> list=new List<Person>();

Person p=new Person();

p.Name="Olive";

p.Sex="";

p.Age=22;

Person p1=new Person();

P1.Name="Moyao";

P1.Sex="";

P1.Age=23;

list.add(p);

list.add(p1);

C#3.0之后

List<Person> list=new List<Person>()

{

new Person(){ Name="Olive",Sex="",Age=22},

new Person(){ Name="Moyao",Sex="",Age=23}

};

5、匿名类型

和隐含类型的局部变量一样,匿名类型就是开发者自定义类型,无须显示定义。在LINQ中匿名类会常常用到。

Var name="Olive";

Var sex="";

Var age=22;

Var person=new{ Name=name,Sex=sex,Age=age};

Consol.WriteLine("名字:"+person.Name"+"性别:"+person.Sex+"年龄:"+person.Age);

实验结果:

6、Lambda表达式

在讲Lambda表达式之前先讲一下委托,和匿名函数。事实上Lambda表达式是由委托——》匿名函数——》Lambda表达式一步步过渡而来的。

6.1委托:

声明委托: public delegate string ShowLove(string name);

委托调用函数:private static string ShowMyLove(string name)

        {

            return "I Love you " + name;

        }

//在主函数里调用该函数,参数为一个委托对象

private static string Show(ShowLove showLove)

        {

            string love = showLove("Olive");

            return love;

        }

结果为:

6.2 2.0中的匿名函数:

这个时候可以将上边的Show方法写成这样

Private string Showstring name

{

Delegate(string name)//匿名方法

{

   Return "I Love you " +name;

}

}

匿名方法顾名思义就是没有方法名,但是需要用delegate关键字修饰

6.3 Lambda表达式

事实上Lambda表达式和匿名方法差不多,都是用于产生内联方法,但是Lambda表达式的语法更为简洁。语法如下:

(参数列表) =>表达式或者语句块

上边的例子还可以这样写:

Private string Show((name)=>return "I Love you "+ name;);

产生的效果是一样的。

Lambda表达式和匿名函数的区别在于,Lambda的参数可以不写类型,匿名函数的参数类型必须得确定.

只有一个参数时小括号()和大括号{}可以省略不写,

形如:Show(name=>return "I love you "+name");

同时如果执行的代码只有一句话是关键字return{}也可以省略形如:

Show(name=>"I love you "+name");

如果是需要执行多句话则{}不能省略,形如:

Show(name=>{ string love=name+"116";return love; });

但是如果没有参数时,括号是万不可省略的形如Show(()=>"I Love you");

7、扩展方法

扩展方法多用于对CLR类型进行一些操作的扩展,在3.0之前如果要实现这些操作,一般都是建一下辅助类,扩展方法,能方便的实现这些公共。

在开始做示例之前,先讲些定义扩展方法需要注意的地方:

1、扩展方法只能在静态类中定义并且是静态方法,

2、扩展方法不能与原有方法名冲突,否则将无效

3、扩展方法的参数必须为(this扩展类 类实例,Parameter p

请看示例:比如要对string类进行扩展

//String 的扩展类

    public static class ExtensionString

    {

        public static string ShowLove(this string s)

        {

            return "I Love " + s;

        }

}

调用:Console.WriteLine("Olive".ShowLove());

结果:

8、局部方法

谈到局部方法,首先要说一下局部类,局部类是用Partial修饰的类,可以由多个partial修饰的同名类组合成一个类,局部方法是3.0以后加入的特性,局部方法必须定义在局部类中,但是局部方法的定义和实现可以分开。在这里同时也需要注意,局部的方法的返回值必须是静态的返回值必须是void,可以有参也可以无参,有无方法实现均可。

下边来看示例:

public partial class PartialTest

    {

        partial void Show(string name);

    }

    public partial class PartialTest

    {

        partial void Show(string name)

        {

            Console.WriteLine("名字:" + name);

        }

}

在主函数中调用

PartialTest p=new PartialTest();

//p.Show();//这个时候你会发现对象p里根本没有Show()方法,因为默认的Partial方法为私有方法,可能有人会想有private修饰一下,这个时候也不能这样做,只需要它是私有的就可以了

那么该如何调用局部方法呢?

我们可以在对象的构造函数里进行调用:

以上的代码做如下修改

public partial class PartialTest

{

PatrialTest( string name)

{

Show(sname);

}

        partial void Show(string name)

        {

            Console.WriteLine("名字:" + name);

        }

}

结果:

在这里需要注意的是局部函数是私有类型的,但是不能用Private来修饰,如果需要调用的话,可以在构造函数里进行调用。

9、yield关键字

我们知道如果想要能够foreach遍历的话,必须要实现IEnumerable接口,GetEnumerator()方法,而yield关键字是用来帮助IEnumerable对象自动生成一个辅助IEnumerator对象。但是yield关键字只能用在retur关键字或break关键字之前。

请看示例:(该示例引自Rookie_J博客)

(1)定义一个实现了接口IEnumerable的类MyYield:

class MyYield : IEnumerable
  {
  publicint StartCountdown;
public IEnumerator GetEnumerator()
       {
  for (int i= StartCountdown; i>=0; i--)
  yieldreturn i;//yield自动生成一个实现了接口IEnumerator的类
     }

}

(2)建立Myield类的对象,且通过foreach实现列举功能:

MyYield myYield=new MyYield() { StartCountdown=10};

foreach (int nin myYield)
{
        Console.WriteLine(n);
}

10、查询语法。

学到这里,你基本上已经把学习LINQ的前期铺垫给做好了,下面就来接触下我们要学习的LINQ查询语法吧。在这里只是做一个简单的介绍,让大家对此有个大致的了解,下一节我会具体的介绍LINQ的查询语法。

还是以上边创建的Person类为例:

            List<Person> list = new List<Person>() { new Person() { Name = "Olive", Age = 22, Sex = "" }, new Person() { Name = "Moyao", Age = 22, Sex = "" } };

Var linqperson=from  p in list where p.Name="Moyao" select p;

Foreach(Person p in linqperson)

{

Console.WriteLine(p.Name+"-----"+p.Age+"---p.Sex);

}

结果如下:    

先做一个大概的解析LINQ语法形式:from   in    where   select

SQL语法形式:select  from  where

是不是很像呢?

好吧,下一节我会慢慢给大家分享。