LINQ 查詢作業中的類型關聯性 (C#)
若要有效地撰寫查詢,您應該了解完整查詢作業中的變數類型如何彼此相關。 如果您了解這些關聯性,則可更輕鬆地理解文件中的 LINQ 範例和程式碼範例。 此外,您將了解使用 var
讓變數成為隱含類型時發生的情況。
LINQ 查詢作業在資料來源、查詢本身和查詢執行中都是強型別。 查詢中的變數類型必須與資料來源中的項目類型以及 foreach
陳述式中的反覆運算變數類型相容。 如果類型錯誤可以在使用者遇到它們之前進行更正,則這個強型別可確保在編譯時期攔截到它們。
為了示範這些類型關聯性,後面的大部分範例都會使用所有變數的明確類型。 最後一個範例示範即使使用隱含類型時,還是如何使用 var
來套用相同原則。
未轉換來源資料的查詢
下圖顯示未對資料執行任何轉換的 LINQ to Objects 查詢作業。 來源包含一系列的字串,而且查詢輸出也是一系列的字串。
- 資料來源的類型引數決定範圍變數的類型。
- 所選取物件的類型會決定查詢變數的類型。
name
是字串。 因此,查詢變數是IEnumerable<string>
。 - 在
foreach
陳述式中,會逐一查看查詢變數。 因為查詢變數是一序列的字串,所以反覆運算變數也是字串。
轉換來源資料的查詢
下圖顯示對資料執行簡單轉換的 LINQ to SQL 查詢作業。 查詢會接受一系列的 Customer
物件作為輸出,並只選取結果中的 Name
屬性。 因為 Name
是字串,所以查詢會產生一系列的字串作為輸出。
- 資料來源的類型引數決定範圍變數的類型。
select
陳述式會傳回Name
屬性,而非完整Customer
物件。 因為Name
是字串,所以custNameQuery
的類型引數是string
,而非Customer
。- 因為
custNameQuery
是一序列的字串,所以foreach
迴圈的反覆運算變數也必須是string
。
下圖顯示稍微複雜的轉換。 select
陳述式會傳回匿名型別,只擷取原始 Customer
物件的兩個成員。
- 資料來源的類型引數一律是查詢中範圍變數的類型。
- 因為
select
陳述式會產生匿名型別,所以必須使用var
讓查詢變數成為隱含類型。 - 因為查詢變數的類型是隱含的,所以
foreach
迴圈中的反覆運算變數也是隱含的。
讓編譯器推斷類型資訊
雖然您應該了解查詢作業中的類型關聯性,但可以選擇讓編譯器為您執行所有工作。 var 關鍵字可以用於查詢作業中的任何區域變數。 下圖與先前討論的範例 2 類似。 不過,編譯器會提供查詢作業中每個變數的強型別。
LINQ 和泛型型別 (C#)
LINQ 查詢以泛型型別為基礎。 您不需要深入了解泛型,就可以開始撰寫查詢。 不過,您可能需要了解兩個基本概念:
- 建立泛型集合類別 (例如 List<T>) 的執行個體時,請將 "T" 取代為清單中會包含之物件的類型。 例如,字串的清單是以
List<string>
表示,而Customer
物件的清單則是以List<Customer>
表示。 泛型清單是強型別,而且優點多於以 Object 形式儲存項目的集合。 如果您嘗試將Customer
新增至List<string>
,則會在編譯時收到錯誤。 由於不需要執行執行階段類型轉換,因此您可以輕鬆使用泛型集合。 - IEnumerable<T> 介面藉由使用
foreach
陳述式來列舉泛型集合類別。 泛型集合類別支援 IEnumerable<T>,就像 ArrayList 這類非泛型集合類別支援 IEnumerable。
如需泛型的詳細資訊,請參閱泛型。
LINQ 查詢中的 IEnumerable<T> 變數
LINQ 查詢變數的類型為 IEnumerable<T> 或衍生類型 (如 IQueryable<T>)。 當您看到類型為 IEnumerable<Customer>
的查詢變數時,只表示查詢在執行時會產生由零個以上的 Customer
物件所組成的序列。
IEnumerable<Customer> customerQuery =
from cust in customers
where cust.City == "London"
select cust;
foreach (Customer customer in customerQuery)
{
Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}
讓編譯器處理泛型型別宣告
如果您想要,也可以使用 var 關鍵字避免使用泛型語法。 var
關鍵字會指示編譯器查看 from
子句中指定的資料來源,來推斷查詢變數的類型。 下列範例會產生與上一個範例相同的已編譯程式碼:
var customerQuery2 =
from cust in customers
where cust.City == "London"
select cust;
foreach(var customer in customerQuery2)
{
Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}
當變數的類型很明顯,或不需要明確指定巢狀泛型型別 (例如群組查詢所產生的巢狀泛型型別) 時,var
關鍵字會很有用。 一般而言,如果使用 var
,建議您考慮到它會讓其他人更難看懂您的程式碼。 如需詳細資訊,請參閱隱含型別區域變數。