1. 程式人生 > >基於Visual Studio2010講解C 4個新特性

基於Visual Studio2010講解C 4個新特性

               

Csharp4.0與以往版本的基礎了體現了強大的效能優勢,主要體現於四個方面:

1. 通過委託成員來實現介面

  在C# 4.0中可以通過委託來實現某個成員的介面,例如下面的程式碼:

[c-sharp] view plain copy print?
  1. publicclass Foo : IList   
  2. {   
  3. private List _Collection implements IList;   
  4. public Foo()   
  5. {   
  6. _Collection = new List();   
  7. }   
  8. }  
  public class Foo : IList   {   private List _Collection implements IList;   public Foo()   {   _Collection = new List();   }   }

  被封閉的成員可以用委託實現一個或多個介面,多個介面用逗號分隔。這麼做可以去掉很多冗餘的程式碼,就像上面的示例,不再需要在封閉類(Foo類)上寫一大堆方法來將介面實現交給成員變數,介面的實現會直接對映到受委託的介面實現(_Collection成員變數)。這個功能同樣增強了對minxins的支援。

  這個就是“委託模式”了,wikipedia上對此模式的解釋如下:

  委託模式是指一個物件對外表現某種行為,但事實上只是將實現此行為的任務將會給一個相關的成員的技術,這種技術反轉了責任。委託模式是加強組合 (聚合)、minxins及aspects的一種基本模式。

  再進一步,在委託實現介面之餘,我們也應當可以自由地重寫某些方法如下:

[c-sharp] view plain copy print?
  1. publicclass Foo : IList   
  2.   {   
  3.   private List _Collection { getset; } implements IList;   
  4.   public
     Foo()   
  5.   {   
  6.   _Collection = new List();   
  7.   }   
  8.   //這將覆蓋委託的執行
  9.   // 漂亮的混入和方便的功能
  10.  pattern implementation   
  11.   publicint IList.Add(string value)   
  12.   {   
  13.   if (!_Collection.Contains(value))   
  14.   _Collection.Add(value);   
  15.   }   
  16.   }  
public class Foo : IList   {   private List _Collection { get; set; } implements IList;   public Foo()   {   _Collection = new List();   }   //這將覆蓋委託的執行  // 漂亮的混入和方便的功能 pattern implementation   public int IList.Add(string value)   {   if (!_Collection.Contains(value))   _Collection.Add(value);   }   }

  2. 匿名返回型別

  在C#中匿名型別可以擁有像普通的類宣告一樣的地位。(當前)匿名型別只能用於區域性變數,不能作為方法的返回值。但是如果一個強型別的LINQ查詢的返回型別可以作為方法的返回型別一定很好,比如下面的程式碼:

[c-sharp] view plain copy print?
  1. public var GetProductInfos()   
  2.   {   
  3.   var productInfos =   
  4.   from p in products   
  5.   select new { p.ProductName, p.Category, Price = p.UnitPrice };   
  6.   return productInfos;   
  7.   }  
public var GetProductInfos()   {   var productInfos =   from p in products   select new { p.ProductName, p.Category, Price = p.UnitPrice };   return productInfos;   }

  3. 一些 Duck-typing or Structural Subtyping 型別的支援

  如果一個類中的某一個方法/屬性的簽名和某個介面一樣,並且這個類沒有實現此介面,那麼這個類就將隱式地實現這個介面。只有這個類實現了介面規定的所有方法/屬性的時候才被認為隱式地實現了此介面。

  如果這東西走起來像鴨子,晃起來像鴨子,那麼這就是鴨子!(James Riley)

  那麼這個和Structural Subtyping有什麼區別?我承認structural subtyping更適合C#的靜態樣式,所以這是個'static duck typing',或者如wikipedia所述:

  Duck typing與structural typing的區別僅在於型別中被訪問的部分在執行期才做相容性確認。

  我們將通過一個用例來說明這種方法有什麼好處:

  在.NET框架中,一部分控制元件實現了一個叫ReadOnly的屬性,比如TextBox, DataGrid, NumericUpDown

  現在我們建一個叫IReadOnlyRestricable的介面

[c-sharp] view plain copy print?
  1. publicinterface IReadOnlyRestricable   
  2.   {   
  3.   bool ReadOnly { getset; }   
  4.   }  
public interface IReadOnlyRestricable   {   bool ReadOnly { get; set; }   }

  然後我們要遍歷所有的控制元件,找出有ReadOnly屬性的控制元件並把此屬性設為true(這些控制元件本身沒有實現IReadOnlyRestricable),在ducktyping下我們可以把控制元件通過型別轉換為IReadOnlyRestricable,就像下面程式碼一樣,這樣我們就不需要通過反射去定位ReadOnly屬性了:

[c-sharp] view plain copy print?
  1. foreach (Control c in f.Controls)   
  2.   {   
  3.   //希望有隱式轉換
  4. IReadOnlyRestrictable ifinterface contract isinclass we are checking against   
  5.   IReadOnlyRestricable editable = c as IReadOnlyRestricable;   
  6.   if (editable != null)   
  7.   editable.ReadOnly = true;   
  8.   }  
foreach (Control c in f.Controls)   {   //希望有隱式轉換IReadOnlyRestrictable if interface contract is in class we are checking against   IReadOnlyRestricable editable = c as IReadOnlyRestricable;   if (editable != null)   editable.ReadOnly = true;   }

  在我看來ducktyping的最大好處是可以為你不需要訪問的類庫定義一些介面,這可以儘可能地減少相互依賴,你可以檢視Phil Haacks more extensive post on duck typing這文章來看看為什麼作者相信這對C#有好處。

  Krzysztof Cwalina認為,很顯然的,C#的foreach關鍵字已經使用了duck typing.

  4. 安全的null延遲賦值操作符

  我很想看到一種安全地訪問一個值為null的物件的屬性的表示式,表示式可能形如Object.Property.Property.Value

  比如我要訪問Customer?.FirstName,但是Customer是null,此時Customer?.FirstName會返回null而不是丟擲個NullReferenceException

  再看看下面的程式碼,你就會知道怎麼用了:

[c-sharp] view plain copy print?
  1. //如果不是客戶或命令無效,這將丟擲一個像往常一樣空引用異常
  2. int orderNumber = Customer.Order.OrderNumber;   
  3. //這將無法編譯,因為它需要一個空的返回型別  
  4. int orderNumber = Customer.Order?.OrderNumber;   
  5. //這將返回null,如果客戶是空或者如果命令是空  
  6. int? orderNumber = Customer?.Order?.OrderNumber;   
  7. if (orderNumber.HasValue)   
  8. //... 用它做一些事情
  9. //而不是必須做
  10. if ((Customer != null) && (Customer.Order != null))   
  11. int a = Customer.Order.OrderNumber  
//如果不是客戶或命令無效,這將丟擲一個像往常一樣空引用異常int orderNumber = Customer.Order.OrderNumber; //這將無法編譯,因為它需要一個空的返回型別  int orderNumber = Customer.Order?.OrderNumber; //這將返回null,如果客戶是空或者如果命令是空  int? orderNumber = Customer?.Order?.OrderNumber; if (orderNumber.HasValue) //... 用它做一些事情//而不是必須做if ((Customer != null) && (Customer.Order != null)) int a = Customer.Order.OrderNumber