程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> LINQ的演變及其對C#設計的影響(4)

LINQ的演變及其對C#設計的影響(4)

編輯:關於C語言

匿名類型

如果我們想繼續使用我們現有的語法來返回名稱和地址,我們很快便會面臨問題,即不存在僅包含 Name 和 Address 的類型。雖然我們仍然可以編寫此查詢,但是必須引入該類型:

class CustomerTuple
{
 public string Name;
 public string Address;
 public CustomerTuple(string name, string address)
 {
  this.Name = name;
  this.Address = address;
 }
}

然後我們才能使用該類型,即此處的 CustomerTuple,以生成我們查詢的結果。

IEnumerable locals =customers.Where(c => c.ZipCode == 91822).Select(c => new CustomerTuple(c.Name, c.Address));

那確實像許多用於投影出字段子集的樣板代碼。而且還往往不清楚如何命名此種類型。CustomerTuple 確實是個好名稱嗎?如果投影出 Name 和 Age 又該如何命名?那也可以叫做 CustomerTuple。因此,問題在於我們擁有樣板代碼,而且似乎無法為我們創建的類型找到任何恰當的名稱。此外,還可能需要許多不同的類型,如何管理這些類型很快便可能成為一個棘手的問題。

這正是匿名類型要解決的問題。此功能主要允許在無需指定名稱的情況下創建結構化類型。如果我們使用匿名類型重新編寫上述查詢,其代碼如下所示:

locals = customers.Where(c => c.ZipCode == 91822)
 .Select(c => new { c.Name, c.Address });

此代碼會隱式創建一個具有 Name 和 Address 字段的類型:

class
{
 public string Name;
 public string Address;
}

此類型不能通過名稱引用,因為它沒有名稱。創建匿名類型時,可顯式聲明字段的名稱。例如,如果正在創建的字段派生於一條復雜的表達式,或純粹不需要名稱,就可以更改名稱:

locals = customers.Where(c => c.ZipCode == 91822)
  .Select(c => new { FullName = c.FirstName + “ “ + c.LastName,
  HomeAddress = c.Address });

在此情形下,生成的類型具有名為 FullName 和 HomeAddress 的字段。

這樣我們又向理想世界前進了一步,但仍存在一個問題。您將發現,我在任何使用匿名類型的地方都策略性地省略了局部變量的類型。顯然我們不能聲明匿名類型的名稱,那我們如何使用它們?

隱式類型化部變量

還有另一種語言功能被稱為隱式類型化局部變量(或簡稱為 var),它負責指示編譯器推斷局部變量的類型。例如:

var integer = 1;

在此例中,整數具有 int 類型。請務必明白,這仍然是強類型。在動態語言中,整數的類型可在以後更改。為說明這一點,以下代碼不會成功編譯:

var integer = 1;

integer = “hello”;

C# 編譯器將報告第二行的錯誤,表明無法將字符串隱式轉換為 int。

在上述查詢示例中,我們現在可以編寫完整的賦值,如下所示:

var locals =
  customers
  .Where(c => c.ZipCode == 91822)
  .Select(c => new { FullName = c.FirstName + “ “ + c.LastName,
  HomeAddress = c.Address });

局部變量的類型最終成為 IEnumerable<?>,其中“?”是無法編寫的類型的名稱(因為它是匿名的)。

隱式類型化局部變量只是:方法內部的局部變量。它們無法超出方法、屬性、索引器或其他塊的邊界,因為該類型無法顯式聲明,而且“var”對於字段或參數類型而言是非法的。

事實證明,隱式類型化局部變量在查詢的環境之外非常便利。例如,它有助於簡化復雜的通用實例化:

var customerListLookup = new Dictionary<STRING, ListCustomer>();

現在我們的查詢取得了良好進展;我們已經接近理想的語法,而且我們是用通用語言功能來達成的。

有趣的是,我們發現,隨著越來越多的人使用過此語法,經常會出現允許投影超越方法邊界的需求。如我們以前所看到的,這是可能的,只要從 Select 內部調用對象的構造函數來構建對象即可。但是,如果沒有用來准確接受您需要設置的值的構造函數,會發生什麼呢?

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved