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"
03-21
<think>嗯,用户想了解如何在C#或VB.NET中使用LINQ技术。首先,我需要回忆一下LINQ的基本概念和语法结构。LINQ全称是Language Integrated Query,允许在.NET语言中进行数据查询,支持多种数据源,比如集合、数据库、XML等。用户可能希望知道基本语法和常见操作,比如查询表达式和方法语法。 接下来,用户可能关心如何在C#和VB.NET中分别实现LINQ查询。C#使用类似SQL的语法,而VB.NET的语法更接近自然语言。例如,C#中的from...where...select结构,而VB.NET使用From...Where...Select。需要分别举例说明,并展示两种语言的差异。 然后,用户可能想了解LINQ的实际应用场景,比如操作集合、数据库(通过Entity Framework或LINQ to SQL)、XML处理等。需要提供具体的代码示例,例如筛选集合中的元素、分组、排序,以及连接数据库查询的例子。 另外,用户可能对LINQ的方法语法和查询表达式语法的区别感兴趣。比如,方法语法使用Lambda表达式,而查询表达式更声明式。需要说明两者的选择依据,比如复杂查询时可能更适合用查询表达式,而简单操作用方法语法更简洁。 还需要注意用户提到的引用内容,特别是引用[2]中提到的VB.NET匿名类在Group by多列时需要指定Key的问题。这可能涉及到在LINQ中使用匿名类型进行分组时的注意事项,需要指出在VB.NET中必须将所有分组字段标记为Key,否则无法正确分组。同时,引用[3]提到VB.NET的名称变化和特性,比如My命名空间、泛型等,但LINQ部分需要重点突出。 此外,用户可能想知道LINQ的性能优化、延迟执行与立即执行的区别,以及如何调试LINQ查询。需要简要提及这些方面,并给出相关示例,例如使用.ToList()强制立即执行,或者使用日志记录中间结果。 最后,生成相关问题时要覆盖LINQ的基本概念、语法差异、应用场景、性能优化和常见问题处理。确保问题能够引导用户进一步深入学习,比如如何结合Entity Framework使用LINQ,或者如何处理复杂的分组和连接操作。</think>### LINQ技术详解(C#/VB.NET) LINQ(Language Integrated Query)是.NET框架中实现数据查询的编程模型,支持强类型查询和智能提示。其核心语法分为**查询表达式**和**方法语法**两种形式。 #### 一、基础语法对比 1. **C#实现** ```csharp // 查询表达式 var result = from p in products where p.Price > 100 select p.Name; // 方法语法(Lambda表达式) var result = products.Where(p => p.Price > 100).Select(p => p.Name); ``` 2. **VB.NET实现** ```vbnet ' 查询表达式 Dim result = From p In Products Where p.Price > 100 Select p.Name ' 方法语法 Dim result = Products.Where(Function(p) p.Price > 100).Select(Function(p) p.Name) ``` #### 二、关键应用场景 1. **集合操作**(筛选/分组/排序) ```csharp // 多条件分组(注意VB.NET需指定Key属性[^2]) var groupedData = from item in orders group item by new { item.CustomerID, item.Year } into g select new { g.Key, Total = g.Sum(x => x.Amount) }; ``` 2. **数据库交互**(Entity Framework) ```csharp using (var context = new NorthwindContext()) { var query = from c in context.Customers where c.City == "London" select new { c.Name, c.Phone }; } ``` 3. **XML处理** ```csharp XElement xmlDoc = XElement.Load("data.xml"); var prices = from item in xmlDoc.Elements("Product") where (double)item.Element("Price") > 50 select item.Element("Name").Value; ``` #### 三、技术特性对比 | 特性 | C#实现 | VB.NET实现 | |-----------------|-------------------------------|----------------------------------| | 匿名类型初始化 | `new { Name = "A", Value = 1 }` | `New With {.Name = "A", .Value = 1}` | | 分组多列处理 | 自动识别组合键 | 必须声明所有Key字段[^2] | | 空值处理 | 使用`??`操作符 | 使用`If()`运算符 | #### 四、优化建议 1. **延迟执行机制**:LINQ默认采用延迟加载,使用`.ToList()`或`.ToArray()`可强制立即执行 2. **复合查询**:优先使用`join...on`替代多个`Where`子句 3. **索引利用**:对`List<T>`使用`AsParallel()`启用并行查询 ```vbnet ' VB.NET中的特殊语法[^3] Dim query = Aggregate book In Books Where book.Price > 50 Into Average(book.Price) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值