【C#】Microsoft C# 之 LINQ 查询语法视频学习总结

1、LINQ - 限制操作符(Restriction Operators)

  • The where clause of a LINQ query restricts the output sequence. Only the elements that match a condition are added to the output sequence.
  • 译文:LINQ查询的where子句限制了输出顺序。只有符合条件的元素才会被添加到输出序列中。

1.1 LINQ 查询结构(LINQ query structure)

  • This sample uses where to find all elements of an array less than 5. It demonstrates the components of a query, including a where clause that filters for small numbers.
  • 译文:这个示例使用where查找小于5的数组中的所有元素。它演示了查询的组件,包括过滤小数的where子句。
csharp 复制代码
using System;
//using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            //List<int> numbers = new List<int>(){ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }
            var lowNums = from num in numbers
                          where num < 5
                          select num;

            Console.WriteLine("Numbers < 5");
            foreach (var x in lowNums)
            {
                Console.WriteLine(x);
            }
        }
    }
}
console 复制代码
Numbers < 5
4
1
3
2
0

1.2 筛选属性上的元素(Filter elements on a property)

  • This sample uses where to find all products that are out of stock. Its where clause examines a property of the items in the input sequence.
  • 译文:这个示例使用where来查找所有缺货的产品。它的where子句检查输入序列中项的属性。
csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // 获取对应列表数据
            List<Product> products = GetTransactionList();

            var soldOutProducts = from prod in products
                                  where prod.UnitsInStock == 0
                                  select prod;

            Console.WriteLine("Sold out products:");
            foreach (var product in soldOutProducts)
            {
                Console.WriteLine($"{product.ProductName} is sold out!");
            }
        }
    }
}

1.3 过滤多个属性上的元素(Filter elements on multiple properties)

  • This sample uses where to find all products that are in stock and cost more than 3.00 per unit.
  • 译文:此示例使用where查找库存中且单价超过3.00的所有产品
csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // 获取对应列表数据
            List<Product> products = GetProductList();

            var expensiveInStockProducts = from prod in products
                                  		   where prod.UnitsInStock > 0 && prod.UnitPrice > 3.00M
                                  		   select prod;

            Console.WriteLine("In-stock products that cost more than 3.00:");
            foreach (var product in soldOutProducts)
            {
                Console.WriteLine($"{product.ProductName} is in stock and costs more than 3.00.");
            }
        }
    }
}

1.4 检查输出元素的序列属性(Examine a sequence property of output elements)

  • This sample uses where to find all customers in Washington and then uses the resulting sequence to drill down into their orders.
  • 译文:本示例使用where查找华盛顿的所有客户,然后使用结果序列向下钻取他们的订单
csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Customer> customers = GetCustomerList();

            var waCustomers = from cust in customers
                              where cust.Region == "WA"
                              select cust;

            Console.WriteLine("Customers from Washington and their orders:");
            foreach (var customer in waCustomers)
            {
                Console.WriteLine($"Customer {customer.CustomerID}: {customer.CompanyName}");
                foreach (var order in customer.Customers)
                {
                    Console.WriteLine($"  Order {order.OrderID}: {order.OrderDate}");
                }
            }
        }
    }
}

1.5 基于位置的过滤元素(Filter elements based on position)

  • this sample demonstrates an indexed Where clause that returns digits whose name is shorter than their value.
  • 译文:这个示例演示了一个索引的Where子句,该子句返回数字名称短于它们的值
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

            var shortDigits = digits.Where((digit, index) => digit.Length < index);

            Console.WriteLine("Short digits:");
            foreach (var d in shortDigits)
            {
                Console.WriteLine($"The word {d} is shorter than its value.");
            }
        }
    }
}
console 复制代码
Short digits:
The word five is shorter than its value.
The word six is shorter than its value.
The word seven is shorter than its value.
The word eight is shorter than its value.
The word nine is shorter than its value.
  • Notice that this final example shows the Where method rather than the where clause. The two forms are equivalent.
  • 译文:注意,最后一个示例显示的是Where方法,而不是Where子句。这两种形式是等价的。

2、LINQ - 生产操作员(Production Operators)

  • The select clause of a LINQ query projects the output sequence. It transforms each input element into the shape of the output sequence.
  • 译文:LINQ查询的select子句投射输出序列。它将每个输入元素转换成输出序列的形状

2.1 Select子句(Select clause)

  • This sample uses select to produce a sequence of ints one higher than those in an existing array of ints. It demonstrates how select can modify the input sequence.
  • 译文:这个示例使用select生成一个比现有整数数组中的整数高一个的整数序列。它演示了select如何修改输入序列。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

            var numsPlusOne = from n in numbers
                              select n + 1;

            Console.WriteLine("Numbers + 1:");
            foreach (int i in numsPlusOne)
            {
                Console.WriteLine(i);
            }
        }
    }
}
console 复制代码
Numbers + 1:
6
5
2
4
10
9
7
8
3
1

2.2 选择单个属性(Select a single property)

  • This sample uses select to return a sequence of just the names of a list of products.
  • 译文:这个示例使用select返回一个产品列表的名称序列。
csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // 获取对应列表数据
            List<Product> products = GetProductList();

            var productNames = from p in products
                               select p.ProductName;

            Console.WriteLine("Product Names:");
            foreach (var productName in productNames)
            {
                Console.WriteLine(productName);
            }
        }
    }
}

2.3 选择变换(Transform with select)

  • This sample uses select to produce a sequence of strings representing the text version of a sequence of ints.
  • 译文:这个示例使用select生成一个字符串序列,表示整数序列的文本版本。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

            var textNums = from n in numbers
                           select strings[n];

            Console.WriteLine("Number strings:");
            foreach (var s in textNums)
            {
                Console.WriteLine(s);
            }
        }
    }
}
console 复制代码
Number strings:
five
four
one
three
nine
eight
six
seven
two
zero

3、LINQ - 分区算子(Partition Operators)

  • The methods Take, Skip, TakeWhile and ShipWhile partition an output sequence. You use these to limit the portion of an input sequence transferred to the output sequence.
  • 译文:Take、Skip、TakeWhile和Shipwhile方法划分一个输出序列。您可以使用它们来限制传输到输出序列的输入序列的部分。

3.1 任务元素(Take elements)

  • This sample uses Take to get only the first 3 elements of the array.
  • 译文:这个示例使用Take只获取数组的前3个元素。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            
            var first3Numbers = numbers.Take(3);

            Console.WriteLine("First 3 numbers:");
            foreach (int n in first3Numbers)
            {
                Console.WriteLine(n);
            }
        }
    }
}
console 复制代码
First 3 numbers:
5
4
1

3.2 嵌套任务分区(Nested Take partitions)

  • This sample uses Take to get the first 3 orders from customers in Washington.
  • 这个示例使用Take获取来自华盛顿客户的前3个订单。
csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Customer> customers = GetCustomerList();

            var first3WAOrders = (
                from cust in customers
                from order in cust.Orders
                where cust.Region == "WA"
                select (cust.CustomerID, order.OrderID, order.OrderDate))
                .Take(3);

            Console.WriteLine("First 3 orders in WA:");
            foreach (var order in first3WAOrders)
            {
                Console.WriteLine(order);
            }
        }
    }
}

3.3 跳过元素(Skip elements)

  • This sample uses Skip to get all but the first 4 elements of the array.
  • 译文:这个示例使用Skip获取数组中除前4个元素外的所有元素。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            
            var allButFirst4Numbers = numbers.Skip(4);

            Console.WriteLine("All but first 4 numbers:");
            foreach (int n in allButFirst4Numbers)
            {
                Console.WriteLine(n);
            }
        }
    }
}
console 复制代码
All but first 4 numbers:
9
8
6
7
2
0

3.4 嵌套跳过分区(Nested skip partitions)

  • This sample uses Skip to get all but the first 2 orders from customers in Washington.
  • 译文:此示例使用Skip获取来自华盛顿客户的除前2个订单外的所有订单
csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Customer> customers = GetCustomerList();

            var waOrders = from cust in customers
                		   from order in cust.Orders
                		   where cust.Region == "WA"
                	  	   select (cust.CustomerID, order.OrderID, order.OrderDate);
            
            var allButFirst2Orders = waOrders.Skip(2);

            Console.WriteLine("All but first 2 orders in WA:");
            foreach (var order in allButFirst2Orders)
            {
                Console.WriteLine(order);
            }
        }
    }
}

3.5 TakeWhile 语法(TakeWhile syntax)

  • This sample uses TakeWhile to return elements starting from the beginning of the array until a number is hit that is not less than 6.
  • 译文:这个示例使用Takewhile返回从数组开头开始的元素,直到击中一个不小于6的数字。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            
            var firstNumberLessThan6 = numbers.TakeWhile(n => n < 6);

            Console.WriteLine("First numbers less than 6:");
            foreach (int num in firstNumberLessThan6)
            {
                Console.WriteLine(num);
            }
        }
    }
}
console 复制代码
First numbers less than 6:
5
4
1
3

3.6 索引 TakeWhile(Indexed TakeWhile)

  • This sample uses TakeWhile to return elements starting from the beginning of the array until a number is hit that is less than its position in the array.
  • 译文:这个示例使用Takewhile返回从数组开头开始的元素,直到击中一个小于其在数组中的位置的数字。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            
            var firstSmallNumber = numbers.TakeWhile((n, index) => n >= index);

            Console.WriteLine("First numbers not less than their position:");
            foreach (int n in firstSmallNumber)
            {
                Console.WriteLine(n);
            }
        }
    }
}
console 复制代码
First numbers not less than their position:
5
4

3.7 SkipWhile 语法(SkipWhile syntax)

  • This sample uses SkipWhile to get the elements of the array starting from the first element divisible by 3.
  • 译文:这个示例使用Skipwhile从第一个能被3整除的元素开始获取数组的元素。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            
            // In the lambda expression, 'n' is the input parameter that identifies each
            // element in the collection in succession. It is inferred to be
            // of type int because numbers is an int array
            // 译文如下:
            // 在lambda表达式中,'n'是连续标识集合中的每个元素的输入参数。
            // 它被推断为int类型,因为numbers是一个int数组
            var allButFirst3Numbers = numbers.SkipWhile(n => n % 3 != 0);

            Console.WriteLine("All elements starting from first element divisible by 3:");
            foreach (int n in allButFirst3Numbers)
            {
                Console.WriteLine(n);
            }
        }
    }
}
console 复制代码
All elements starting from first element divisible by 3:
3
9
8
6
7
2
0

3.8 索引 SkipWhile(Indexed SkipWhile)

  • This sample uses ShipWhile to get the elements of the array starting from the first element less than position.
  • 译文:这个示例使用Shipwhile从第一个小于position的元素开始获取数组的元素。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

            var laterNumbers = numbers.SkipWhile((n, index) => n >= index);

            Console.WriteLine("All elements starting from first element less than its position:");
            foreach (int n in laterNumbers)
            {
                Console.WriteLine(n);
            }
        }
    }
}
console 复制代码
All elements starting from first element less than its position:
1
3
9
8
6
7
2
0

3.9 总结

  • Take:Take(num),num 填几就取多少个元素,如果取出填超过元素个数,则取出全部
  • Skip:Skip(num),num 填几就跳过几个元素之后再取,如果填写超过元素个数,则取出为空
  • TakeWhile:例如 TakeWhile(n => n > 2),从左到右开始判断,到不满足条件的值为止(取前面部分,不包括前面为止的值)
  • SkipWhile:例如 SkipWhile(n => n > 2),从左到右开始判断,到不满足条件的值为止(取后面部分,包括前面为止的值)

4、LINQ - 序列操作(Sequence Operations)

  • These operators compare or manipulate entire sequences: EqualAll, Concat, and Combine.
  • 译文:这些操作符比较或操作整个序列:EqualAll、Concat和Combine。

4.1 比较两个序列是否相等(Compare two sequences for equality)

  • This sample uses EqualAll to see if two sequences match on all elements in the same order.
  • 这个示例使用EqualAll来查看两个序列是否以相同的顺序在所有元素上匹配。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var wordsA = new string[] { "cherry", "apple", "blueberry" };
            var wordsB = new string[] { "cherry", "apple", "blueberry" };

            bool match = wordsA.SequenceEqual(wordsB);

            Console.WriteLine($"The sequences match: {match}");
        }
    }
}
console 复制代码
The sequences match: True
  • Change the order of elements in one sequence and try that sample again:
  • 译文:改变一个序列中元素的顺序并再次尝试该样本:
csharp 复制代码
var wordsB = new string[] { "apple", "blueberry", "cherry" };
  • Notice that sequences are equal if they contain the same elements, and those elements are in the same order.
  • 译文:注意,如果序列包含相同的元素,并且这些元素的顺序相同,则它们是相等的。

4.2 连接两个序列(Concatenate two sequences)

  • This sample uses Concat to create one sequence that contains each array's values, one after the other.
  • 译文:这个示例使用Concat创建一个序列,其中一个接一个地包含每个数组的值。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
            int[] numbersB = { 1, 3, 5, 7, 8 };

            var allNumbers = numbersA.Concat(numbersB);

            Console.WriteLine("All numbers from both arrays:");
            foreach (int n in allNumbers)
            {
                Console.WriteLine(n);
            }
        }
    }
}
console 复制代码
All numbers from both arrays:
0
2
4
5
6
8
9
1
3
5
7
8

4.3 连接两个序列的投影(Concatenate projections from two sequences)

  • This sample uses Concat to create one sequence that contains the names of all customers and products, including any duplicates.
  • 译文:这个示例使用Concat创建一个序列,该序列包含所有客户和产品的名称,包括任何重复的名称。
csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Customer> customers = GetCustomerList();
            List<Product> products = GetProductList();

            var customerNames = from c in customers
                                select c.CompanyName;
            var productNames = from p in products
                               select p.ProductName;

            var allNames = customerNames.Concat(productNames);

            Console.WriteLine("Customer and product names:");
            foreach (var n in allNames)
            {
                Console.WriteLine(n);
            }
        }
    }
}

4.4 组合序列与zip(Combine sequences with zip)

  • This sample calculates the dot product of two integer vectors. It uses Zip to calculate the dot product, passing it a lambda function to multiply two arrays, element by element, and sum the result.
  • 译文:这个示例计算两个整数向量的点积。它使用Zip计算点积,传递给它一个lambda函数,将两个数组逐个元素相乘,并对结果求和。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] vectorA = { 0, 2, 4, 5, 6 };
            int[] vectorB = { 1, 3, 5, 7, 8 };

            int dotProduct = vectorA.Zip(vectorB, (a, b) => a * b).Sum();

            Console.WriteLine($"Dot product: {dotProduct}");
        }
    }
}
console 复制代码
Dot product: 109

5、LINQ - 投影算子(Projection Operators)

  • The select keyword or Select method provide this capability. These operators create output sequence elements from input sequence elements. The output elements may be either same or difference types.
  • 译文:select关键字或select方法提供了这种功能。这些操作符根据输入序列元素创建输出序列元素。输出元素可以是相同类型,也可以是不同类型。

5.1 从多个输入序列中选择(Select from multiple input sequences)

  • This sample uses a compound from clause to make a query that returns all pairs of numbers from both arrays such that the number from numbersA is less than the number from numbersB.
  • 译文:本示例使用复合from子句进行查询,该查询返回来自两个数组的所有数字对,使得来自numbersA的数字小于来自numbersB的数字。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
            int[] numbersB = { 1, 3, 5, 7, 8 };

            var pairs = from a in numbersA
                        from b in numbersB
                        where a < b
                        select (a, b);

            Console.WriteLine("Pairs where a < b");
            foreach (var pair in pairs)
            {
                Console.WriteLine($"{pair.a} is less than {pair.b}");
            }
        }
    }
}
console 复制代码
Pairs where a < b
0 is less than 1
0 is less than 3
0 is less than 5
0 is less than 7
0 is less than 8
2 is less than 3
2 is less than 5
2 is less than 7
2 is less than 8
4 is less than 5
4 is less than 7
4 is less than 8
5 is less than 7
5 is less than 8
6 is less than 7
6 is less than 8

6、LINQ - 懒惰而急切的执行(lazy and eager execution)

  • Learn to specify either eager or lazy query execution
  • 译文:学习指定即时或延迟查询执行

6.1 查询延迟执行(Queries execute lazily)

  • The following sample shows how query execution is dererred until the query is enumerated at a foreach statement.
  • 译文:下面的示例显示了在foreach语句中枚举查询之前,查询执行是如何进行的。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Sequence operators form first-class queries that
            // are not executed until you enumerate over them.
            // 译文如下:
            // 序列操作符形成一级查询,在枚举它们之前不会执行这些查询。

            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

            int i = 0;
            var q = from n in numbers
                    select ++i;

            // Note, the local variable 'i' is not incremented
            // until each element is evaluated (as a side-effect):
            // 译文如下:
            // 注意,局部变量'i'直到每个元素都被求值时才递增(作为副作用):
           
            foreach (var v in q)
            {
                Console.WriteLine($"v = {v}, i = {i}");
            }
            foreach (var v in q)
            {
                Console.WriteLine($"v = {v}, i = {i}");
            }
        }
    }
}
console 复制代码
v = 1, i = 1
v = 2, i = 2
v = 3, i = 3
v = 4, i = 4
v = 5, i = 5
v = 6, i = 6
v = 7, i = 7
v = 8, i = 8
v = 9, i = 9
v = 10, i = 10
v = 11, i = 11
v = 12, i = 12
v = 13, i = 13
v = 14, i = 14
v = 15, i = 15
v = 16, i = 16
v = 17, i = 17
v = 18, i = 18
v = 19, i = 19
v = 20, i = 20

6.2 请求即时查询执行(Request eager query execution)

  • The following sample shows how queries can be executed immediately with operators such as ToList().
  • 译文:下面的示例展示了如何使用ToList()等操作符立即执行查询。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Methods like ToList() cause the query to be
            // executed immediately, caching the results.
            // 译文如下:
            // 像ToList()这样的方法会立即执行查询,缓存结果。

            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

            int i = 0;
            var q = (from n in numbers
                     select ++i)
                     .ToList();

            // The local variable i has already been fully
            // incremented before we iterate the results:
			// 译文如下:
			// 在我们迭代结果之前,局部变量i已经被完全递增了:

            foreach (var v in q)
            {
                Console.WriteLine($"v = {v}, i = {i}"); 
            }
            foreach (var v in q)
            {
                Console.WriteLine($"v = {v}, i = {i}"); 
            }
        }
    }
}
console 复制代码
v = 1, i = 10
v = 2, i = 10
v = 3, i = 10
v = 4, i = 10
v = 5, i = 10
v = 6, i = 10
v = 7, i = 10
v = 8, i = 10
v = 9, i = 10
v = 10, i = 10
v = 1, i = 10
v = 2, i = 10
v = 3, i = 10
v = 4, i = 10
v = 5, i = 10
v = 6, i = 10
v = 7, i = 10
v = 8, i = 10
v = 9, i = 10
v = 10, i = 10
  • You can replace the ToList call with a ToArray. Try it.
  • 译文:你可以用一个ToArray来代替ToList调用。试一试。

6.3 使用新结果重用查询(Reuse queries with new results)

  • The following sample shows how, because of deferred execution, queries can be used again after data changes and will then operate on the new data.
  • 译文:下面的示例显示,由于延迟执行,查询可以在数据更改后再次使用,然后对新数据进行操作。
csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Deferred execution lets us define a query once
            // and then reuse it later after data changes.
            // 译文如下:
            // 延迟执行允许我们定义一次查询,然后在数据更改后重用它。

            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            var lowNumbers = from n in numbers
                             where n <= 3
                             select n;

            Console.WriteLine("First run numbers <= 3:");
            foreach (int n in lowNumbers)
            {
                Console.WriteLine(n);
            }

            for (int i = 0; i < 10; i++)
            {
                numbers[i] = -numbers[i];
            }

            // During this second run, the same query object,
            // lowNumbers, will be iterating over the new state
            // of numbers[], producing different results:
            // 译文如下:
            // 在第二次运行期间,相同的查询对象lowNumbers将迭代numbers[]的新状态,产生不同的结果:
            
            Console.WriteLine("Second run numbers <= 3:");
            foreach (var n in lowNumbers)
            {
                Console.WriteLine(n);
            }
        }
    }
}
console 复制代码
First run numbers <= 3:
1
3
2
0
Second run numbers <= 3:
-5
-4
-1
-3
-9
-8
-6
-7
-2
0

6.4 延迟执行和即时查询的区别

6.4.1 上面 6.3 如果将延迟查询换成即时查询的写法

csharp 复制代码
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            var lowNumbers = (from n in numbers
                              where n <= 3
                              select n).ToList();

            Console.WriteLine("First run numbers <= 3:");
            foreach (int n in lowNumbers)
            {
                Console.WriteLine(n);
            }

            for (int i = 0; i < 10; i++)
            {
                numbers[i] = -numbers[i];
            }

            Console.WriteLine("Second run numbers <= 3:");
            foreach (var n in lowNumbers)
            {
                Console.WriteLine(n);
            }
        }
    }
}
console 复制代码
First run numbers <= 3:
1
3
2
0
Second run numbers <= 3:
1
3
2
0

6.4.2 从控制台输出结果能得知区别

  • 延迟查询只有在进行循环操作的时候才执行查询,且因为是延迟查询的缘故,数据更改后延迟查询还可继续使用
  • 即时查询在最开始 ToList() 之后获取的值就已经算是执行了查询,获取的值相当于是锁死值了,在 6.2 里面控制台输出 i = 10 也能很明显看出来,之后在循环操作不会再执行查询操作
相关推荐
IT规划师4 小时前
开源 - Ideal库 - 常用枚举扩展方法(一)
开源·c#·.net core·ideal库·枚举转换
NetX行者10 小时前
.NET 9震撼来袭:基于.NET 8的五大功能亮点,引领开发新潮流
开发语言·microsoft·c#·.netcore
张某布响丸辣10 小时前
HTTP状态码详解
java·网络·python·网络协议·http·c#
飞舞的哈哈10 小时前
C# 有趣的小程序—桌面精灵详细讲解
c#
Skyshin3412 小时前
C# IEnumerator,IEnumerable ,Iterator
开发语言·c#
ling1s12 小时前
C#核心(7)索引器
开发语言·c#
LKID体13 小时前
win32com库基于wps对Word文档的基础操作
c#·word·wps
金蝶软件小李14 小时前
vector和docker的区别?
开发语言·docker·c#
金蝶软件小李16 小时前
图像处理椒盐噪声
开发语言·图像处理·算法·计算机视觉·c#
小吴同学·16 小时前
(实战)WebApi第13讲:怎么把不同表里的东西,包括同一个表里面不同的列设置成不同的实体,所有的给整合到一起?【前端+后端】、前端中点击标签后在界面中显示
c#·.netcore·.net core