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

发布时间:2023年12月19日

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子句。
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);
            }
        }
    }
}
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子句检查输入序列中项的属性。
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的所有产品
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查找华盛顿的所有客户,然后使用结果序列向下钻取他们的订单
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子句,该子句返回数字名称短于它们的值
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.");
            }
        }
    }
}
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如何修改输入序列。
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);
            }
        }
    }
}
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返回一个产品列表的名称序列。
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生成一个字符串序列,表示整数序列的文本版本。
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);
            }
        }
    }
}
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个元素。
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);
            }
        }
    }
}
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个订单。
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个元素外的所有元素。
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);
            }
        }
    }
}
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个订单外的所有订单
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的数字。
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);
            }
        }
    }
}
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返回从数组开头开始的元素,直到击中一个小于其在数组中的位置的数字。
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);
            }
        }
    }
}
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整除的元素开始获取数组的元素。
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);
            }
        }
    }
}
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的元素开始获取数组的元素。
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);
            }
        }
    }
}
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来查看两个序列是否以相同的顺序在所有元素上匹配。
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}");
        }
    }
}
The sequences match: True
  • Change the order of elements in one sequence and try that sample again:
  • 译文:改变一个序列中元素的顺序并再次尝试该样本:
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创建一个序列,其中一个接一个地包含每个数组的值。
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);
            }
        }
    }
}
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创建一个序列,该序列包含所有客户和产品的名称,包括任何重复的名称。
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函数,将两个数组逐个元素相乘,并对结果求和。
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}");
        }
    }
}
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的数字。
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}");
            }
        }
    }
}
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语句中枚举查询之前,查询执行是如何进行的。
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}");
            }
        }
    }
}
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()等操作符立即执行查询。
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}"); 
            }
        }
    }
}
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.
  • 译文:下面的示例显示,由于延迟执行,查询可以在数据更改后再次使用,然后对新数据进行操作。
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);
            }
        }
    }
}
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 如果将延迟查询换成即时查询的写法

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);
            }
        }
    }
}
First run numbers <= 3:
1
3
2
0
Second run numbers <= 3:
1
3
2
0

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

  • 延迟查询只有在进行循环操作的时候才执行查询,且因为是延迟查询的缘故,数据更改后延迟查询还可继续使用
  • 即时查询在最开始 ToList() 之后获取的值就已经算是执行了查询,获取的值相当于是锁死值了,在 6.2 里面控制台输出 i = 10 也能很明显看出来,之后在循环操作不会再执行查询操作
文章来源:https://blog.csdn.net/weixin_50223520/article/details/135015264
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。