zoukankan      html  css  js  c++  java
  • LINQ新特性简介及入门教程

    出处:http://www.msproject.cn/article/Cs3LinqFeatures.aspx

    翻译
    Amro Khasawneh 著 Understanding LINQ (C#)
    flanker译(还请指教啊)

    简介

    本文主要是关注于LINQ——我认为是VS2008(.NET3.5)中最令人兴奋的特性。LINQ使查询成为了.NET中头等的编程概念,被查询的数据可以是XML(LINQ to XML)、Databases(LINQ to SQL、LINQ to Dataset、LINQ to Entities)和对象(LINQ to Objects)。LINQ也是可扩展的,允许你建立自定义的LINQ数据提供者(比如:LINQ to Amazon、LINQ to NHibernate、LINQ to LDAP)。

    在这里我会讨论C#3.0中的一些新的语言特性和改进,正是它们使得LINQ变得如此强大,让你可以写出这样的代码:

    var result = from c in Customers
                 where c.City == Boston"
                 orderby c.LastName descending
                 select new { c.FirstName, c.LastName, c.Address };
    记住,如果你想要使用LINQ,你需要安装Visual Studio 2008(.NET3.5)。

    新的语言特性

    I/ 自动属性

    public class Point {
        private int _x, _y;
        public int X {
            get { return _x; }
            set { _x = value; }
        }
        public int Y {
            get { return _y; }
            set { _y = value; }
        }
    }
    上面的代码简单的定义了一个拥有两个属性的类。现在,使用VS2008中的C#编译器,我们就可以用自动属性写的更简单,它能自动的生成带有get/set操作的私有域。

    public class Point {
        public int X { get; set; }
        public int Y { get; set; }
    }
    上面的代码可读性更好并且简洁。
    (这个特性和LINQ还没有关系)

    II/ 局部变量类型

    使用这个特性,声明一个局部变量,它的具体类型是通过初始化表达式来推断。这点是通过var关键词完成的(这个使用脚本语言的人应该很熟悉,但它们实际上是有很大区别的)。我们可以写出如下的代码:

    var num = 50;
    var str = "simple string";
    var obj = new myType();
    var numbers = new int[] {1,2,3};
    var dic = new Dictionary<int,myType>();
    编译器会生成IL中间代码,就如同我们编译了下面的代码:

    int num = 50;
    string str = "simple string";
    myType obj = new myType();
    int[] numbers = new int[] {1,2,3};
    Dictionary<int,myType> dic = new Dictionary<int,myType>();
    注意,这里并不存在无类型的变量,也没有推迟类型的绑定。编译器是从右边的赋值语句来自动推断和声明变量的类型的,var关键词是一个强类型的变量引用。

    III/ 对象初始化和集合初始化

    我们继续使用上面的Point类。假设我们想要这个类的一个实例,我们会建立对象并设置它的属性,代码会是这样子的:

    Point p = new Point();
    p.X = 0;
    p.Y = 0;
    现在,使用对象初始化,就可以像这样子来重写:

    Point p = new Point() { X = 0, Y = 0 };
    这个特性也可以使用在集合上,看看下面这段示例:

    List points = new List {
        new Point { X = 2,  Y = 5 },
        new Point { X = 1, Y = -10 },
        new Point { X = 3, Y = 0 }
    };
    注意,编译器会产生和上面相等价的长一些的代码,它依次调用Add()方法来在集合里添加元素。

    IV/ 匿名类型

    这个语言特性让我们可以定义内嵌的类型,而不需要显式地定义一个类型。换句话说,假设我们没有定义Point类,

    却要使用一个Point对象(即类型是匿名的)。我们可以使用上面提到的对象初始化语法,但不用指定类型名:

    var p = new {X = 0, Y = 2};
    在VS2008中,你仍然可以使用智能感应。所以如果你继续使用变量p,就会得到这个匿名类型的属性列表。

    V/ Lambda表达式

    在C#2.0中引入了匿名方法,允许在需要委托的地方写一个代码块。匿名方法提供了函数式程序语言的能力,语法显得很简洁。Lambda表达式提供了一个更简洁的语法来写匿名方法。一个Lambda表达式就是一个参数列表(可以隐式类型),然后是一个=>符号,然后是一个表达式或者一个语句块。

    作为一个示例,我们定义一个委托类型MyDeleg:

    delegate R MyDeleg(A arg);
    然后我们就可以使用匿名方法:

    MyDeleg<int,bool> IsPositive = delegate(int num) {
                                       return num > 0;
                                   };
    我们也可以使用新的Lambda表达式来写:

    MyDeleg<int,bool> IsPositive = num => num > 0;
    VI/ 扩展方法

    扩展方法可以使你来扩展一个已存在的类型,增加它的方法,而无需继承它或者重新编译。所以不像为对象写助手方法,扩展方法可以直接是对象自己的一部分。

    一个示例,假设我们想要验证一个string是不是合法的Email地址,我们可以编写一个方法,输入为一个string并且返回true或者false。现在,使用扩展方法,我们可以如下这样做:

    public static class MyExtensions {
        public static bool IsValidEmailAddress(this string s) {
            Regex regex = new Regex( @"^[w-.]+@([w-]+.)+[w-]{2,4}___FCKpd___12quot; );
            return regex.IsMatch(s);
        }
    }
    我们定义了一个带有静态方法的静态类。注意,那个静态方法在参数类型string前面有一个this关键词,这会告诉编译器这个特殊的扩展方法会增加给string类型的对象。于是我们就可以在string中调用这个成员方法:

    using MyExtensions;

    string email = Request.QueryString["email"];
    if ( email.IsValidEmailAddress() ) {
        // ...
    }
    值得提出的是,LINQ就是使用了System.Linq命名空间中的扩展方法(比如where()、orderby()、select()、sum()、average()等等),而且它定义了标准查询操作符,可以用来查询关系数据库、XML和任何实现了IEnumerable<T>接口的.NET对象。

    VII/ 查询语法

    查询表达式提供了一个语言集成的语法来查询,它特别像关系和层次查询语言比如SQL和XQuery。使用LINQ操作符(也就是from...where...select)写查询很方便,Visual Studio为它提供了很好的智能感知和编译时的检查支持。
    当C#编译器遇到了一个查询语法表达式时,实际上它会被转化为使用扩展方法和Lambda表达式的方法调用。

    我们举一个例子来解释这个:

    var result = from c in Customers
                 where c.City.StartsWith("B")
                 orderby c.LastName
                 select new { c.FirstName, c.LastName, c.Address };
    上面的代码等价于:

    var result = Customers.Where( c => c.City.StartsWith("B") )
                          .OrderBy( c => c.LastName  )
                          .Select( c => new { c.FirstName, c.LastName, c.Address } );
    使用查询语法的好处还有它会使代码更简单更易读。
    同时注意,查询表达式以from开头,以select或者group结尾。

    最后注意

    C#3.0中新引入的几个特性大多数都仅仅是“编译器技巧”或者“语法糖”,其实编译器生成的IL中间代码和原来的是一样的,这样他们就独立于framework和CLR运行时。但是,他们确实需要某些framework的支持,比如System.Core.dll程序集。这就是为什么扩展方法仍然需要依靠于System.Core.dll里包含的System.Runtime.CompilerServices.ExtensionAttribute。
    另一方面,查询表达式只是实现了到扩展方法的映射,它包含在System.Linq, System.Data.Linq和System.Xml.Linq命名空间中。

    参考和资源

    "New Orcas Language Feature" Series by Scott Guthrie: 讲解LINQ的系列文章
    LINQ Resources: Daniel Moth 写的日志
    MSDN Magazine (June 2007): 一篇介绍 C# 3.0 和 LINQ 的文章
    Visual Studio Orcas Samples: C#/VB LINQ 示例
    Future Versions: C# 3.0
    The LINQ Project: LINQ 项目主页 
    文章出处:http://www.diybl.com/course/4_webprogram/asp.net/netjs/2008530/118056_2.html


    文章出处:http://www.diybl.com/course/4_webprogram/asp.net/netjs/2008530/118056.html

  • 相关阅读:
    LOJ2323. 「清华集训 2017」小 Y 和地铁 【搜索】【思维】【好】
    BZOJ2687 交与并/BZOJ2369 区间【决策单调性优化DP】【分治】
    BZOJ1563 NOI2009 诗人小G【决策单调性优化DP】
    LOJ6039. 「雅礼集训 2017 Day5」珠宝【决策单调性优化DP】【分治】【思维好题】
    BZOJ4709 Jsoi2011 柠檬【决策单调性+单调栈】
    BZOJ2216 Poi2011 Lightning Conductor 【决策单调性优化DP】
    BZOJ3675 Apio2014 序列分割 【斜率优化】
    BZOJ4566 Haoi2016 找相同字符【广义后缀自动机】
    51nod 1600 Simple KMP【后缀自动机+LCT】【思维好题】*
    linux usermod
  • 原文地址:https://www.cnblogs.com/im/p/1450647.html
Copyright © 2011-2022 走看看