首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

LINQ 進階:延遲執行機制與非泛型集合查詢

     編輯:關於C#

延遲執行:LINQ 的核心設計

LINQ 查詢定義時不執行,只有在迭代結果 (foreach、ToList、Count 等) 時才真正計算。這帶來兩大優勢:

  1. 資源佔用低:不必一次性加載整個數據源
  2. 數據即時性:數據源變更後,重新迭代自動反映最新結果

延遲執行演示

int[] numbers = { 10, 11, 12, 13, 14 };

Console.WriteLine($"查詢構建: {DateTime.Now}");
var query = from n in numbers select DoubleIt(n);
Console.WriteLine($"查詢構建完成: {DateTime.Now}"); // 幾乎同時

foreach (var result in query)
{
    Console.WriteLine($"結果: {result}, 時間: {DateTime.Now}");
}

int DoubleIt(int x)
{
    Console.WriteLine($"  計算: {x}");
    Thread.Sleep(1000);
    return x * 2;
}

/* 輸出:
查詢構建: 22:41:50
查詢構建完成: 22:41:50
  計算: 10
結果: 20, 時間: 22:41:51
  計算: 11
結果: 22, 時間: 22:41:52
...
*/

數據源變更自動生效

int[] data = { 10, 11, 12 };
var query = from n in data select n * 2;

foreach (var v in query) Console.WriteLine(v); // 20, 22, 24

// 修改源數據
for (int i = 0; i < data.Length; i++) data[i] += 10;

foreach (var v in query) Console.WriteLine(v); // 40, 42, 44 - 自動反映變更!

底層原理:IEnumerator 與 yield return

查詢實際在 GetEnumerator() 中執行,每次 MoveNext() 產生一個元素。

public static IEnumerable<int> MyQuery(int[] source)
{
    foreach (var n in source)
    {
        Console.WriteLine($"  Yield: {n}");
        yield return n * 2; // 狀態機,逐個產生
    }
}

// 使用
foreach (var v in MyQuery(new[] { 1, 2, 3 }))
    Console.WriteLine(v);
/* 輸出交替:
  Yield: 1
  2
  Yield: 2
  4
  ...
*/

強制立即執行

某些場景需要立即物化結果:

  • ToList()、ToArray():緩存到記憶體
  • Count()、Sum()、First():聚合操作需遍歷全集合
var query = from n in numbers select DoubleIt(n);
var list = query.ToList(); // 這裡一次性計算完所有

// 之後再用 list 不會重複計算
Console.WriteLine(list.Count); // 直接返回 5,不再調用 DoubleIt

非泛型集合查詢:Cast<T> 與 OfType<T>

.NET 1.x 時代的 ArrayList 等非泛型集合,元素類型為 object,無法直接 LINQ 查詢。

Cast<T>:強制轉型,失敗拋異常

var list = new ArrayList { 1, 2, 3, 4, 5 };
var query = from int n in list select n; // 隱式 Cast<int>()
foreach (var n in query) Console.WriteLine(n); // 正常

OfType<T>:篩選匹配類型,忽略不匹配

var mixed = new ArrayList { 1, 2, "abc", 3, 4 };
var query = from int n in mixed.OfType<int>() select n;
foreach (var n in query) Console.WriteLine(n); // 1, 2, 3, 4 - "abc" 被靜默忽略

// 若用 Cast<int>() 會拋 InvalidCastException

對照表

方法行為適用場景
Cast<T>()全部轉型,失敗拋異常確定集合內全是 T 類型
OfType<T>()只保留 T 類型,其他忽略混合類型集合,安全篩選
from T x in list編譯器自動插入 Cast<T>()語法糖,等同 Cast

效能提醒

  • 延遲執行下,多次迭代 = 多次計算。需複用結果請 ToList()
  • 集合操作 (Count, Sum, Contains...) 會觸發立即執行並遍歷
  • 大數據源場景,延遲執行可避免記憶體峰值

掌握延遲執行與非泛型兼容,能讓 LINQ 在新舊代碼庫中游刃有餘。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved