查詢運算式
查詢表達式會使用類似 SQL 或 XQuery 的宣告式語法來查詢 System.Collections.Generic.IEnumerable<T> 集合。 在編譯時,編譯器會將查詢語法轉換為方法呼叫,以實現 LINQ 提供者對標準查詢方法的實作。 應用程式會使用 using 指令來指定適當的命名空間,以控制範圍內的標準查詢運算符。 下列查詢表達式會使用字串陣列,根據字串中的第一個字元進行分組,並排序分組。
var query = from str in stringArray
group str by str[0] into stringGroup
orderby stringGroup.Key
select stringGroup;
隱式型別變數(var)
您可以使用 var 修飾詞來指示編譯程式推斷並指派類型,如下所示:
var number = 5;
var name = "Virginia";
var query = from str in stringArray
where str[0] == 'm'
select str;
宣告為 var 的變數是強類型,就像您明確指定類型的變數一樣。 使用 var 使得建立匿名型態成為可能,但僅限於局部變數。 如需詳細資訊,請參閱隱含型別區域變數。
物件與集合初始化器
物件和集合初始化表達式可讓您初始化物件,而不需明確呼叫 物件的建構函式。 通常在查詢表達式中使用初始化器,當它們將來源資料投影至新的資料型態時。 假設一個名為 Customer public Name 和 Phone properties 的類別,你可以像以下程式碼中使用物件初始化器:
var cust = new Customer { Name = "Mike", Phone = "555-1212" };
繼續你的 Customer 類,假設有一個名為 IncomingOrders 的資料來源,對於每筆具有大的 OrderSize 的訂單,你想根據該訂單建立一個新的 Customer。 你可以對這個資料來源執行 LINQ 查詢,並利用物件初始化來填充一個集合:
var newLargeOrderCustomers = from o in IncomingOrders
where o.OrderSize > 5
select new Customer { Name = o.Name, Phone = o.Phone };
資料來源可能定義的屬性比類別多 Customer ,例如 OrderSize,但透過物件初始化,查詢回傳的資料會被塑造成想要的資料型態;你可以選擇與類別相關的資料。 因此,您現在擁有一個填入了您想要的新System.Collections.Generic.IEnumerable<T>的Customer。 你也可以用 LINQ 的方法語法寫出前面的範例:
var newLargeOrderCustomers = IncomingOrders.Where(x => x.OrderSize > 5).Select(y => new Customer { Name = y.Name, Phone = y.Phone });
從 C# 12 開始,您可以使用 集合運算式 來初始化集合。
如需詳細資訊,請參閱:
匿名型別
編譯程式會建構 匿名型別。 只有編譯器能存取型別名稱。 匿名類型可讓您在查詢結果中暫時將一組屬性分組,而不需要定義個別的具名類型。 你可以用新的表達式和物件初始化器來初始化匿名型別,如圖所示:
select new {name = cust.Name, phone = cust.Phone};
從 C# 7 開始,您可以使用 Tuple 來建立未命名的類型。
擴充成員
擴充成員是靜態類別中與一種稱為接收者型別相關聯的靜態成員。 你可以把分機成員當作接收者類型來呼叫。 這個功能讓你可以在不實際修改現有類型的情況下「新增」成員。 標準查詢運算符是一組擴充方法,可為實作 IEnumerable<T>的任何類型提供LINQ查詢功能。
Lambda 運算式
Lambda 表達式是一種內聯函式,利用=>運算子將輸入參數與函數主體分離,並可在編譯時轉換為代理或表達式樹。 在 LINQ 程式設計中,當您對標準查詢運算符進行直接方法呼叫時,會遇到 Lambda 表達式。
表達式視為數據
查詢對像是可組合的,這表示您可以從 方法傳回查詢。 代表查詢的物件不會儲存產生的集合,而是在需要時產生結果的步驟。 從方法回傳查詢物件的優點是你可以進一步組合或修改它們。 因此,任何回傳查詢的方法的回傳值或 out 參數也必須包含該型別。 如果方法將查詢具體化為具體 List<T> 或 Array 類型,則會傳回查詢結果,而不是查詢本身。 你仍然可以組合或修改從某個方法回傳的查詢變數。
在下列範例中,第一個方法 QueryMethod1 會傳回查詢做為傳回值,而第二個方法 QueryMethod2 會以參數傳回查詢 out (returnQ 在範例中)。 在這兩種情況下,回傳的都是查詢,而不是查詢結果。
IEnumerable<string> QueryMethod1(int[] ints) =>
from i in ints
where i > 4
select i.ToString();
void QueryMethod2(int[] ints, out IEnumerable<string> returnQ) =>
returnQ = from i in ints
where i < 4
select i.ToString();
int[] nums = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
var myQuery1 = QueryMethod1(nums);
以下 foreach 迴圈執行查詢 myQuery1。
foreach (var s in myQuery1)
{
Console.WriteLine(s);
}
將滑鼠指標放在上方 myQuery1 以查看其類型。
你也可以直接執行從 返回的 QueryMethod1 查詢,而不必使用 myQuery1。
foreach (var s in QueryMethod1(nums))
{
Console.WriteLine(s);
}
將滑鼠指標停留在呼叫 QueryMethod1 上方,以檢視其回傳類型。
QueryMethod2 傳回查詢結果作為 out 的參數值:
QueryMethod2(nums, out IEnumerable<string> myQuery2);
// Execute the returned query.
foreach (var s in myQuery2)
{
Console.WriteLine(s);
}
您可以使用查詢組合來修改查詢。 在此情況下,會使用先前的查詢物件來建立新的查詢物件。 這個新物件會傳回與原始查詢物件不同的結果。
myQuery1 = from item in myQuery1
orderby item descending
select item;
// Execute the modified query.
Console.WriteLine("\nResults of executing modified myQuery1:");
foreach (var s in myQuery1)
{
Console.WriteLine(s);
}