Linq

Linq

所有常用用法汇总介绍整理,来自于 LINQ之路系列博客导航 - Life a Poem - 博客园 (cnblogs.com)

通用示例为

string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
  • Where:返回符合给定条件的elements子集(Where支持第二个可选参数为index位置)

    var query = names.Where((n, i) => i % 2 == 0);
  • Take & Skip:返回开始的N个元素,忽略剩下的元素;忽略开始的N个元素,返回之后的元素

    // 假设用户在一个图书数据库中查找包含"mercury"的所有图书
        // 如果查找结果包含100条记录,下面的查询会返回前面20条
        IQueryable<Book> query = dataContext.Books
            .Where(b => b.Title.Contains("mercury"))
            .OrderBy(b => b.Title)
            .Take(20);
    
        // 下面的查询则返回第21到40行数据(第2页)
        IQueryable<Book> query = dataContext.Books
            .Where(b => b.Title.Contains("mercury"))
            .OrderBy(b => b.Title)
            .Skip(20).Take(20);
        }
  • TakeWhile & SkipWhile:遍历输入,返回每一个元素,直到遇到一个不符合的,忽略剩下的;遍历输入,忽略每一个元素,直到遇到一个不符合的,返回剩下的

    int[] numbers = { 3, 5, 2, 234, 4, 1 };
        var takeWhileSmall = numbers.TakeWhile(n => n < 100); // { 3, 5, 2 }
        var skipWhileSmall = numbers.SkipWhile(n => n < 100); // { 234, 4, 1 }
  • Distinct:去除重复

    char[] distinctLetters = "HelloWorld".Distinct().ToArray();
        string s = new string(distinctLetters); // HeloWrd
  • Select: 转换每一个元素,个数一样

    string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
        IEnumerable<string> query = names
            .Select((s, i) => i + "=" + s); // { "0=Tom", "1=Dick", ... }
  • SelectMany:转换元素,个数不一样,多层Select

    string[] fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };
        IEnumerable<string> query = fullNames.SelectMany(name => name.Split());
        foreach (string name in query)
            Console.Write(name + "|"); // Anne|Williams|John|Fred|Smith|Sue|Green|
  • OrderBy & OrderByDescending:升序排列;降序排列

  • ThenBy & ThenByDescending:前一次排序相同键值元素重新升序排列;降序排列

    string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
       
       //按姓名长度进行排序
       IEnumerable<string> query = names.OrderBy(s => s.Length);
       // Result: { "Jay", "Tom", "Mary", "Dick", "Harry" };
       
     //Jay和Tom、Mary和Dick,除非我们添加额外的ThenBy运算符
       IEnumerable<string> query = names.OrderBy(s => s.Length).ThenBy(s => s);
       // Result: { "Jay", "Tom", "Dick", "Mary", "Harry" };
  • GroupBy:读取每一个元素,放入一个临时列表中,key相同的元素会被放入同一个子列表中

    string[] files = Directory.GetFiles("c:\\temp");
        IEnumerable<IGrouping<string, string>> query =
            files.GroupBy(file => Path.GetExtension(file));
    
        foreach (IGrouping<string, string> grouping in query)
        {
            Console.WriteLine("Extension: " + grouping.Key);
            foreach (string filename in grouping)
                Console.WriteLine(" - " + filename);
        }
        
        // Result:
        Extension: .pdf
         - chapter03.pdf
         - chapter04.pdf
        Extension: .doc
         - todo.doc
         - menu.doc
         - Copy of menu.doc
        ...
  • First & FirstOrDefault:第一个元素

  • Last & LastOrDefault:最后一个元素

    int[] numbers = { 1, 2, 3, 4, 5 };
    
        int firstEven = numbers.First(n => n % 2 == 0);     // 2
        int lastEven = numbers.Last(n => n % 2 == 0);       // 4
        
        int firstBigError = numbers.First(n => n > 10); // Exception
        int firstBigNumber = numbers.FirstOrDefault(n => n > 10); // 0
  • ElementAt & ElementOrDefault:特定位置元素

    int[] numbers = { 1, 2, 3, 4, 5 };
        int third = numbers.ElementAt(2);       // 3
        
        int tenthError = numbers.ElementAt(9);  // Exception
        int tenth = numbers.ElementAtOrDefault(9);  // 0
  • Count & LongCount:返回元素个数;返回元素个数(64-bit整数)

  • Min & Max:返回最小元素;返回最大元素

  • Sum & Average:求和;求平均数

  • Contains:包含

  • Any:任意元素满足条件返回true

  • All:所有元素满足条件返回true

  • SequenceEqual:比较两个sequence,若他们拥有相同元素、相同顺序,返回true

  • Concat & Union:两个sequence所有元素;两个sequence所有元素,去重

    int[] seq1 = { 1, 2, 3 }, seq2 = { 3, 4, 5 };
        IEnumerable<int> concat = seq1.Concat(seq2); // { 1, 2, 3, 3, 4, 5 }
        IEnumerable<int> union = seq1.Union(seq2); // { 1, 2, 3, 4, 5 }
  • Intersect & Except:两个sequence都存在元素;第一个sequence有,第二个sequence没有的所有元素

    int[] seq1 = { 1, 2, 3 }, seq2 = { 3, 4, 5 };
        IEnumerable<int>
        commonality = seq1.Intersect(seq2), // { 3 }
        difference1 = seq1.Except(seq2), // { 1, 2 }
        difference2 = seq2.Except(seq1); // { 4, 5 }
  • Zip: 同步遍历两个sequence, 返回的sequence基于在每一个元素对上应用lambda表达式

    int[] numbers = { 3, 5, 7 };
        string[] words = { "three", "five", "seven", "ignored" };
        IEnumerable<string> zip = numbers.Zip (words, (n, w) => n + "=" + w);
     
        // 产生的sequence包含如下元素
        // 3=three
        // 5=five
        // 7=seven
  • OfType & Cast:接收一个非泛型集合,返回一个泛型集合,前者遇到不能转换的会忽略,后者会抛异常

    DateTime offender = DateTime.Now;
        ArrayList classicList = new ArrayList(); // in System.Collections
        classicList.Add(offender);
        IEnumerable<int>
        sequence2 = classicList.OfType<int>(), // OK - ignores offending DateTime
        sequence3 = classicList.Cast<int>(); // Throws exception
  • ToArray & ToList & ToDictionary:

  • Repeat & Range:只能操作int整数,前者重复某个数值,后者是索引和元素个数

    foreach (int i in Enumerable.Repeat(5, 3))
            Console.Write(i + ""); // 5 5 5
        foreach (int i in Enumerable.Range(5, 5))
            Console.Write(i + ""); // 5 6 7 8 9

隐式类型变量 var

自动属性

简化定义字段和属性

注意:定义自动属性时,必须同时提供getset关键字,所以不能定义只读或者只写的自动属性

class Person
    {
        private string firstName = string.Empty;
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }
    }
//-------------------------------------------------------
    class Person
    {
        public string FirstName { get; set; }
    }

匿名类型

相当于临时的自定义类,来封装一些数据

var data = new { Name = "Hello", Age = 1 };
    Debug.LogFormat("{0},{1}", data.Name,data.Age);

匿名类型的相等语义,Equals重写时基于值,==重写时基于引用

static void AnonymousTypeEqualityTest()
    {
        // 构建两个匿名类型,拥有相同的名称/值对
        var worker1 = new { FirstName = "Harry", SecondName = "Folwer", Level = 2 };
        var worker2 = new { FirstName = "Harry", SecondName = "Folwer", Level = 2 };

        // Equals测试
        if (worker1.Equals(worker2))
            Console.WriteLine("worker1 equals worker2");
        else
            Console.WriteLine("worker1 not equals worker2");

        // ==测试
        if (worker1 == worker2)
            Console.WriteLine("worker1 == worker2");
        else
            Console.WriteLine("worker1 != worker2");

        // Type Name测试
        if (worker1.GetType().Name == worker2.GetType().Name)
            Console.WriteLine("we are both the same type");
        else
            Console.WriteLine("we are different types");
    }

拓展方法

Lambda表达式

对象初始化器
public class Point
    {
        public int X { get; set; }
        public int Y { get; set; }
    }
 
    static void ObjectInitSyntax()
    {
        // 手动初始化各属性
        Point aPoint = new Point();
        aPoint.X = 10;
        aPoint.Y = 20;
 
        // 使用新的对象初始化语法进行初始化
        Point bPoint = new Point { X = 10, Y = 20 };
    }

查询运算符
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
        
    var list = names
        .Where(n => n.Contains("a"))
        .OrderBy(n => n.Length)
        .Select(n => n.ToUpper());

    foreach (string name in list) Debug.Log(name);

子查询
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
    // 获取所有长度最短的名字(注意:可能有多个)
    IEnumerable<string> outQuery = names
        .Where(n => n.Length == names     

            .OrderBy(n2 => n2.Length)
            .Select(n2 => n2.Length).First());      // Tom, Jay"
06-26
### LINQ 技术文档与使用指南概述 LINQ(Language Integrated Query)是 C# 中一种强大的查询语言,允许开发者以统一的方式处理各种数据源,如集合、数据库和 XML 文档。它通过集成在 C# 语言中的语法,简化了传统查询操作,并提升了代码的可读性和可维护性。 #### 查询语法 LINQ 提供了两种主要的查询语法形式:**查询表达式语法** 和 **方法语法**。查询表达式语法更接近 SQL 风格,适合编写复杂的查询逻辑;而方法语法则基于 Lambda 表达式,适用于简洁的操作链式调用。 以下是一个使用查询表达式语法的示例: ```csharp var filteredData = from item in dataList where item.Value > 10 select item; ``` 该代码从 `dataList` 中筛选出值大于 10 的元素,并将结果存储到 `filteredData` 中。 相比之下,使用方法语法的等效代码如下: ```csharp var filteredData = dataList.Where(item => item.Value > 10); ``` #### 延迟执行与立即执行 LINQ 查询分为**延迟执行**和**立即执行**两种模式。延迟执行意味着查询的实际执行会推迟到遍历结果时进行,这种方式可以提高性能,特别是在处理大型数据集时。例如: ```csharp var query = from item in dataList where item.IsActive select item; ``` 只有在对 `query` 进行迭代时,如使用 `foreach` 循环,查询才会实际执行。 另一方面,立即执行是指查询在定义后立即执行并返回结果。常见的立即执行操作包括 `ToList()` 和 `ToArray()` 等聚合函数: ```csharp var activeItems = (from item in dataList where item.IsActive select item).ToList(); ``` 上述代码中,`ToList()` 触发了查询的立即执行,并将结果存储为一个列表。 #### 性能优化建议 尽管 LINQ 提供了便捷的查询方式,但在处理大规模数据时需要注意性能问题。以下是几个优化技巧: - **避免不必要的多次枚举**:某些操作可能导致查询被多次执行,增加开销。可以通过缓存中间结果来减少重复计算。 - **选择合适的数据结构**:根据需求选择合适的集合类型,如使用 `HashSet<T>` 实现快速查找。 - **合理使用 `AsEnumerable()` 和 `AsQueryable()`**:在需要切换 LINQ 提供程序时,明确指定执行环境,避免意外行为 [^1]。 #### 数据源支持 LINQ 支持多种数据源的查询操作,包括但不限于: - **内存中的集合**:通过 `System.Linq.Enumerable` 类实现,适用于数组、列表等本地数据。 - **数据库**:借助 Entity Framework 等 ORM 框架,LINQ 可以直接用于数据库查询。 - **XML 文档**:通过 `System.Xml.Linq` 命名空间提供的类,LINQ 能够高效解析和操作 XML 数据。 例如,查询 XML 文档的代码可能如下: ```csharp XDocument doc = XDocument.Load("data.xml"); var elements = from element in doc.Descendants("Item") where (int)element.Element("Value") > 10 select element; ``` #### 扩展性与自定义查询提供程序 LINQ 的设计具有高度扩展性,开发者可以创建自定义的查询提供程序,以便在特定数据源上实现 LINQ 查询功能。这通常涉及实现 `IQueryable` 和 `IQueryProvider` 接口,并定义相关的表达式树解析逻辑。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值