☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
C# 基礎 中級

🔍 LINQ 查詢語言

📌 什麼是 LINQ?

LINQ(Language Integrated Query)就像是 C# 裡的 SQL。 它讓你可以用簡潔的語法對集合(陣列、List 等)進行查詢、篩選、排序。

// 想像你有一堆學生成績,要找出及格的人
int[] scores = { 85, 42, 97, 63, 28, 74, 91, 55 }; // 成績陣列

// 不用 LINQ 的寫法(傳統迴圈)
List<int> passingOld = new List<int>();  // 建立新 List
foreach (int score in scores)            // 走訪每個成績
{
    if (score >= 60)                     // 如果及格
    {
        passingOld.Add(score);           // 加入 List
    }
}

// 用 LINQ 的寫法(一行搞定!)
var passing = scores.Where(s => s >= 60).ToList(); // 篩選出 >= 60 的成績
// passing = [85, 97, 63, 74, 91, 55]

📌 方法語法 vs 查詢語法

var students = new List<(string Name, int Score)>  // 學生清單(用 Tuple)
{
    ("小明", 85),   // 小明 85 分
    ("小美", 92),   // 小美 92 分
    ("小華", 68),   // 小華 68 分
    ("小強", 45),   // 小強 45 分
    ("小芳", 78),   // 小芳 78 分
};

// 方法語法(Method Syntax)— 最常用
var topStudents = students
    .Where(s => s.Score >= 70)          // 篩選 70 分以上
    .OrderByDescending(s => s.Score)    // 依分數降冪排序
    .Select(s => s.Name)               // 只取名字
    .ToList();                          // 轉成 List
// topStudents = ["小美", "小明", "小芳"]

// 查詢語法(Query Syntax)— 像 SQL
var topStudents2 =
    (from s in students                 // 從 students 中
     where s.Score >= 70                // 篩選 70 分以上
     orderby s.Score descending         // 依分數降冪排序
     select s.Name)                     // 只取名字
    .ToList();                          // 轉成 List
// 結果和方法語法一樣

📌 Where — 篩選

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

// 篩選偶數
var evens = numbers.Where(n => n % 2 == 0);  // n 除以 2 餘 0 就是偶數
// evens = [2, 4, 6, 8, 10]

// 篩選大於 5 的數
var big = numbers.Where(n => n > 5);  // n 大於 5
// big = [6, 7, 8, 9, 10]

// 多條件篩選
var filtered = numbers.Where(n => n > 3 && n < 8);  // 3 < n < 8
// filtered = [4, 5, 6, 7]

📌 Select — 轉換

int[] numbers = { 1, 2, 3, 4, 5 };  // 原始數字

// 每個數字乘以 2
var doubled = numbers.Select(n => n * 2);  // 轉換每個元素
// doubled = [2, 4, 6, 8, 10]

// 轉換成字串
var strings = numbers.Select(n => $"數字 {n}");  // 轉換成描述文字
// strings = ["數字 1", "數字 2", ...]

// 轉換成匿名物件
var objects = numbers.Select(n => new  // 轉換成物件
{
    Value = n,              // 原始值
    Square = n * n,         // 平方
    IsEven = n % 2 == 0     // 是否為偶數
});

foreach (var obj in objects)  // 走訪每個物件
{
    Console.WriteLine($"{obj.Value}: 平方={obj.Square}, 偶數={obj.IsEven}");
}

📌 OrderBy / GroupBy / Join

var products = new List<(string Name, string Category, decimal Price)>
{
    ("蘋果", "水果", 30),     // 水果類
    ("牛奶", "飲料", 45),     // 飲料類
    ("香蕉", "水果", 20),     // 水果類
    ("咖啡", "飲料", 60),     // 飲料類
    ("橘子", "水果", 25),     // 水果類
};

// OrderBy — 排序
var sorted = products.OrderBy(p => p.Price);  // 依價格升冪排序
var sortedDesc = products.OrderByDescending(p => p.Price);  // 降冪排序

// 多欄位排序
var multiSort = products
    .OrderBy(p => p.Category)           // 先依類別排序
    .ThenByDescending(p => p.Price);    // 同類別再依價格降冪

// GroupBy — 分組
var groups = products.GroupBy(p => p.Category);  // 依類別分組

foreach (var group in groups)  // 走訪每個分組
{
    Console.WriteLine($"== {group.Key} ==");  // Key 是分組的依據
    foreach (var item in group)  // 走訪分組內的每個項目
    {
        Console.WriteLine($"  {item.Name}: {item.Price} 元");
    }
}
// 輸出:
// == 水果 ==
//   蘋果: 30 元
//   香蕉: 20 元
//   橘子: 25 元
// == 飲料 ==
//   牛奶: 45 元
//   咖啡: 60 元

// Join — 合併兩個集合
var categories = new[] { ("水果", "🍎"), ("飲料", "🥤") };  // 類別與圖示

var joined = products.Join(
    categories,                     // 要合併的集合
    p => p.Category,                // 左邊的 key
    c => c.Item1,                   // 右邊的 key
    (p, c) => $"{c.Item2} {p.Name} - {p.Price}元"  // 合併後的結果
);
// joined = ["🍎 蘋果 - 30元", "🥤 牛奶 - 45元", ...]

📌 First / Any / Count 等查詢方法

int[] numbers = { 5, 3, 8, 1, 9, 2, 7 };  // 數字陣列

// First / FirstOrDefault — 取第一個
int first = numbers.First();                    // 取第一個元素 → 5
int firstBig = numbers.First(n => n > 6);       // 第一個 > 6 的 → 8
int firstOrDef = numbers.FirstOrDefault(n => n > 100);  // 找不到 → 回傳 0

// Single — 取唯一一個(如果有多個會拋出例外)
// int single = numbers.Single(n => n > 8);    // 只有 9 符合 → 9
// int singleFail = numbers.Single(n => n > 5); // 多個符合 → 拋出例外!

// Any / All — 是否存在 / 是否全部符合
bool hasNegative = numbers.Any(n => n < 0);     // 有負數嗎?→ false
bool allPositive = numbers.All(n => n > 0);     // 全部是正數?→ true

// Count — 計數
int total = numbers.Count();                     // 總共幾個 → 7
int bigCount = numbers.Count(n => n > 5);        // > 5 的有幾個 → 3

📌 聚合方法

int[] scores = { 85, 92, 68, 45, 78 };  // 成績陣列

// 基本聚合
int sum = scores.Sum();                  // 總和 → 368
double avg = scores.Average();           // 平均 → 73.6
int max = scores.Max();                  // 最大值 → 92
int min = scores.Min();                  // 最小值 → 45

// Aggregate — 自定義聚合(進階)
// 把所有名字用逗號串起來
string[] names = { "小明", "小美", "小華" };
string joined = names.Aggregate((a, b) => $"{a}, {b}");
// joined = "小明, 小美, 小華"

// 用 Aggregate 計算階乘
int factorial = Enumerable.Range(1, 5)  // 產生 1, 2, 3, 4, 5
    .Aggregate((a, b) => a * b);        // 1*2*3*4*5 = 120
Console.WriteLine($"5! = {factorial}"); // 輸出:5! = 120

📌 鏈式操作

// LINQ 最強大的地方:把多個操作串在一起
var result = Enumerable.Range(1, 100)   // 產生 1 到 100
    .Where(n => n % 3 == 0)             // 篩選 3 的倍數
    .Select(n => new { Value = n, Square = n * n }) // 計算平方
    .OrderByDescending(x => x.Square)   // 依平方降冪排序
    .Take(5)                            // 只取前 5 個
    .ToList();                          // 轉成 List

foreach (var item in result)  // 走訪結果
{
    Console.WriteLine($"{item.Value} 的平方 = {item.Square}");
}
// 輸出(3 的倍數中平方最大的前 5 個):
// 99 的平方 = 9801
// 96 的平方 = 9216
// 93 的平方 = 8649
// 90 的平方 = 8100
// 87 的平方 = 7569

🤔 我這樣寫為什麼會錯?

❌ 錯誤:忘記 LINQ 是延遲執行

var numbers = new List<int> { 1, 2, 3 };
var query = numbers.Where(n => n > 1);  // 這裡還沒真正執行查詢!

numbers.Add(4);  // 加入新元素

// ❌ 以為 query 只有 [2, 3]
// ✅ 實際上 query = [2, 3, 4](因為 LINQ 是在 foreach 時才執行)
foreach (var n in query) Console.Write($"{n} ");
// 輸出:2 3 4

// 解法:如果要立即執行,加上 .ToList()
var list = numbers.Where(n => n > 1).ToList();  // 立即執行並存結果
numbers.Add(5);  // 這次不會影響 list

❌ 錯誤:First() 找不到元素

int[] nums = { 1, 2, 3 };

// ❌ 錯誤:First() 找不到符合條件的元素會拋出 InvalidOperationException
// int x = nums.First(n => n > 100);  // 拋出例外!

// ✅ 正確:用 FirstOrDefault()
int x = nums.FirstOrDefault(n => n > 100);  // 找不到回傳 0

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊