• LINQ解析:LINQ to Objects简介


    可以查询的内容:不是所有的对象都可以使用LINQ to Objects查询,使用LINQ to Objects的首要条件是:需要查询的对象是实现了IEnumerable<T>接口的集合类型;说明:本篇中的例子兼顾使用查询表达式和查询操作符

    1. 数组

    包括元素类型为Object在内的所有类型的数组都可以使用LINQ to Objects,示例如下:

    using System;
    using System.Linq;

    class ArrayTest
    {
    class Cutomer
    {
    public Cutomer(String name, String company, UInt16 age)
    {
    Name = name;
    Company = company;
    Age = age;
    }

    public string Name { get; set; }
    public string Company { get; set; }

    private ushort age;
    public ushort Age
    {
    get { return age; }
    set
    {
    if (value > 200 || value < 1)
    throw new ArgumentOutOfRangeException("age", "Age must between 1 and 200!");

    age = value;
    }
    }
    }

    static void Main()
    {
    Object[] array = { 's', "String", true, 28, 26.7, 27.6F, 18UL, new Cutomer("Steven Xue", "Google", 25) };

    var types =
    array
    .Select(item => item.GetType().Name)
    .OrderBy(type => type);

    ObjectDumper.Write(types);
    }
    }

    输出如下:

    Boolean
    Char
    Cutomer
    Double
    Int32
    Single
    String
    UInt64

    以下示例是强类型的数组:

    using System;
    using System.Collections.Generic;
    using System.Linq;

    class TypedArrayTest
    {
    class Book
    {
    public String Isbn { get; set; }
    public Int32 PageCount { get; set; }
    public Decimal Price { get; set; }
    public String Publisher { get; set; }
    public String Title { get; set; }
    public String[] Authors { get; set; }

    public override String ToString()
    {
    return Title;
    }
    }

    static void Main()
    {
    Book[] books = {
    new Book { Title="LINQ in Action" },
    new Book { Title="JavaScript in Action" },
    new Book { Title="CLR Via C#" }
    };

    var titles =
    books
    .Where(book => book.Title.Contains("LINQ"))
    .Select(book => book.Title);

    ObjectDumper.Write(titles);
    }
    }

    输出如下:

    LINQ in Action

    说明:ObjectDumper是一个非常有用的辅助类,能够显示对象中的数据,随微软的LINQ示例代码提供(具体位置:VS安装目录\Samples \1033目录下的CSharpSamples.zip中提供了ObjectDumper辅助类);从上面的例子可以看出,查询能够应用在元素为自定义类 型的数组上,以上示例为Cutomer和Book类


    2. 泛型列表

    以下列出主要的泛型列表:

    System.Collections.Generic.List<T>
    System.Collections.Generic.LinkedList<T>
    System.Collections.Generic.Queue<T>
    System.Collections.Generic.Stack<T>
    System.Collections.Generic.HashSet<T>
    System.Collections.ObjectModel.Collection<T>
    System.ComponentModel.BindingList<T>

    示例如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;

    class GenericListTest
    {
    class Book
    {
    public String Isbn { get; set; }
    public Int32 PageCount { get; set; }
    public Decimal Price { get; set; }
    public String Publisher { get; set; }
    public String Title { get; set; }
    public String[] Authors { get; set; }

    public override String ToString()
    {
    return Title;
    }
    }

    static void Main()
    {
    List<Book> books = new List<Book>() {
    new Book { Title="LINQ in Action" },
    new Book { Title="JavaScript in Action" },
    new Book { Title="CLR Via C#" }
    };

    var titles =
    books
    .Where(book => book.Title.Contains("LINQ"))
    .Select(book => book.Title);

    ObjectDumper.Write(titles);
    }
    }

    输出如下:

    LINQ in Action

    注意:查询语句与强类型数组的示例一模一样,没有作任何的改变,因为无论是数组还是列表都实现了同样的IEnumerable<Book>接口


    3. 泛型字典


    泛型字典实现了IEnumerable<KeyValuePair<TKey, TValue>>接口,KeyValuePair结构包含了强类型的Key和Value属性,以下列出主要的泛型字典:

    System.Collections.Generic.Dictionary<TKey, TValue>
    System.Collections.Generic.SortedDictionary<TKey, TValue>
    System.Collections.Generic.SortedList<TKey, TValue>

    示例如下:

    class GenericDictionaryTest
    {
    static void Main()
    {
    Dictionary<int, string> numbers;
    numbers = new Dictionary<int, string>();
    numbers.Add(0, "America");
    numbers.Add(1, "China");
    numbers.Add(2, "England");
    numbers.Add(3, "Australia");
    numbers.Add(4, "French");
    numbers.Add(5, "Japan");

    //取键值为偶数的字典元素
    var evenNumbers =
    from number in numbers
    where (number.Key & 1) == 0
    select number.Value;

    ObjectDumper.Write(evenNumbers);
    }
    }


    4. 字符串

    System.String看上去并不像是个集合,但它的确实现了IEnumerable<Char>接口,因此可以使用LINQ to Objects对其进行操作,示例如下:

    class StringTest
    {
    static void Main()
    {
    var count =
    "Do you know that man? I can't remember him!"
    .Where(c => !Char.IsLetter(c))
    .Count();
    Console.WriteLine(count);
    }
    }

    输出:11

    注意:智能感知不会自动为String给出LINQ相关的扩展方法,因为很少有人将String作为IEnumerable<Char>处理


    5. 其他集合

    可以用LINQ to Objects与其他任何实现了IEnumerable<T>接口的集合配合使用,非泛型的集合实现了IEnumerable接口,却没有实 现IEnumerable<T>接口,不过可以借助Cast和OfType查询操作符对非泛型集合进行查询,这个以后再谈


    上面的例子都是控制台应用程序,下面分别用ASP.NET和Windows Forms举两个例子

    ASP.NET示例如下:

    查询代码:

    var books = new Book[]{
    new Book {Title="LINQ in Action", Price=65, Authors=new String[]{"Fabrice Marguerie","Steve Eichert","Jim Wooley"}},
    new Book {Title="CLR Via C#", Price=95, Authors=new String[]{"Jeffrey Richter"}},
    new Book {Title="C# in depth", Price=69, Authors=new String[]{"Jon Skeet"}},
    new Book {Title="ASP.NET AJAX in Action", Price=59, Authors=new String[]{"Alessandro Gallo","David Barkol","Rama Krishna Vavilala"}},
    new Book {Title="Essential C# 4.0", Price=89, Authors=new String[]{"Mark Michaelis"}},
    new Book {Title="NHibernate in Action", Price=55, Authors=new String[]{"Pierre Henri Kuate","Tobin Harris","Christian Bauer","Gavin King"}}
    };

    GridView1.DataSource =
    from book in books
    where book.Title.Length > 15
    orderby book.Price
    select new { book.Title, FirstAuthor = book.Authors[0] };

    GridView1.DataBind();

    页面上添加一个GridView:

    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="true">
    </asp:GridView>

    运行效果如下图所示:




    注意:在上述代码中,返回了包含三个属性的匿名类型的集合,这三个属性的类型将由编译器根据属性的值得出,分别为String、Decimal和 String;GridView通过反射得到数据源中对象的各个属性,因此自动生成的列的顺序是无法控制的,不能认为生成列的顺序一定会与绑定对象中属性 的定义顺序保持一致;匿名类型带来的好处:借助于匿名类型,无需在GridView中显式指定列名,程序无需为了组合数据而创建专门的类型,在某些情况 下,甚至能够通过匿名类型将领域模型映射成表现层模型

    Windows Forms示例如下:

    在窗体上添加一个DataGridView控件,添加如下代码:

    using System;
    using System.Linq;
    using System.Windows.Forms;

    namespace WinFormTest
    {
    public sealed partial class FormMain : Form
    {
    private static volatile FormMain form;
    private static Object objLock = new Object();

    private FormMain()
    {
    InitializeComponent();
    }

    private void FormMain_Load(object sender, EventArgs e)
    {
    String[] books = { "LINQ in Action", "CLR Via C#", "C# in depth", "ASP.NET AJAX in Action",
    "Essential C# 4.0", "NHibernate in Action", "jQuery in Action", "Expert C# 2008 Business Objects"};

    var query =
    from book in books
    where book.Length > 18
    orderby book
    select new { Book = book };

    dataGridView1.DataSource = query.ToList();
    }

    //单例模式,使用双重锁定
    public static FormMain Instance
    {
    get
    {
    if (form == null)
    {
    lock (objLock)
    {
    if (form == null)
    {
    form = new FormMain();
    }
    }
    }

    return form;
    }
    }
    }
    }

    运行效果如下图所示:




    注意:这里通过匿名类型封装了图书的标题,因为DataGridView控件会默认显示绑定对象的属性,因此若是直接将图书的标题以字符串的形式绑定上去 的话,看到的将是这个字符串的长度,因为Length属性是字符串的唯一属性(可以尝试将查询表达式的最后一句 select new { Book = book } 改为 select book 查看结果);返回的结果序列被转化为一个列表,这是DataGridView控件在进行数据绑定时所必需的,否则要借助于BindingSource对象 来完成绑定

    作者:Lucifer Xue
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Springboot使用ehcache缓存
    Tomcat启用HTTPS协议配置过程
    细说document.ready和window.onload
    科技创新
    SpringBoot的ApplicationRunner
    禁用Chrome的“请停用以开发者模式运行的扩展程序”提示
    论文排版问题
    mathType换行等号对齐
    内部类调用外部类的成员,同名时怎么调用?
    Tomcat的manager app管理web项目
  • 原文地址:https://www.cnblogs.com/SevenXue/p/1865909.html
Copyright © 2020-2023  润新知