程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> C#3.0教程:自動屬性和擴展方法

C#3.0教程:自動屬性和擴展方法

編輯:關於.NET

使用自動屬性後,你可以不用手工聲明一個私有成員變量以及編寫get/set邏輯,取而代之的是,編譯器會自動為你生成一個私有變量和默認的get/set 操作。系統為你產生的私有變量在IDE中,你是看不到的,如下圖:

 

當然如果你希望屬性中有些賦值或者取值邏輯校驗,自動屬性可是不適合你的。

上面的代碼我們編譯後,再用 Reflector 反編譯後,我們可以看到上述代碼中的屬性變成了如下代碼:這個編譯器給我們產生的私有變量,顯然不是那麼容易重名的。


[CompilerGenerated] 
private string <>k__AutomaticallyGeneratedPropertyFIEld0; 

public string Name 

[CompilerGenerated] 
get 

return this.<>k__AutomaticallyGeneratedPropertyFIEld0; 


[CompilerGenerated] 
set 

this.<>k__AutomaticallyGeneratedPropertyFIEld0 = value; 


注意:如果你只希望屬性有 get 或者 set 方法,這些情況都是無法使用 自動屬性的,需要你自己來書寫。否則就會報如下的錯誤:

'ConsoleApplication1.MyClass.Name.set' must declare a body because it is not marked abstract or extern. Automatically implemented propertIEs must define both get and set Accessors.

但是 get 和 set 訪問級別不一樣,比如一個是 public,一個是 internal,則可以書寫成下述方式,而不會報錯誤。

public int ID { get; internal set; }

今天早上在MSDN站點看到這樣一篇文章: C# 3.0 LINQ 的演變及其對 C# 設計的影響 。 從這篇文章我們就可以明顯的看到,C# 3.0 所新增的這些特性,可以認為都是為了LINQ 的發展,為了LINQ更易用,所創建的一些新特性,當然這些新特性也可以被非LINQ相關功能所使用。LINQ的發展,帶動了C#3.0 這一系列新特性的產生。

回來說我們的話題,擴展方法,首先看一個最簡單的代碼例子:

擴展方法的定義,需要注意三個部分:1、靜態類(私有公共都可以);2、靜態方法(私有公共都可以);3、第一個函數參數前帶 this(必須是第一參數前)

namespace Hongjun.Guo 

static class MyExtensionMethods 

internal static void Print(this object s) 

Console.WriteLine(s); 


}

擴展方法的使用,需要注意點: using 你定義所在的命名空間。


using Hongjun.Guo; 

static void Main(string[] args) 

object o = "dsdgs"; 
o.Print(); 

這樣一個簡簡單單的代碼後,我們就可以很方便的對一些不開源的第三方控件增加很多我們自己額外需要的功能。

擴展方法的使用,有時候並不是這麼簡簡單單,我們來看一些特殊情況,通過這些特殊情況的分析,我們可以更深入的了解擴展方法:

情況一 : 擴展方法跟原來類的方法重名時候的處理邏輯。

場景:我們是對一個第三方的沒有開放源代碼組件的一個類擴展了一個方法,比如方法: Print 。過了一段時間後,這個第三方的組件發布了新版本,該類的增加了 Print 方法。這時候會出何種效果??

問題演示代碼:


namespace Hongjun.Guo 


public class MyClass 

public void Print() 

Console.WriteLine("****"); 



static class MyExtensionMethods 

internal static void Print(this MyClass s) 

Console.WriteLine("haha " + s.ToString()); 





調用范例:


using Hongjun.Guo; 

static void Main(string[] args) 

MyClass o = new MyClass(); 
o.Print(); 

Console.ReadLine(); 
}
 

這時候我們會看到何種結果呢??

答案:看到的是 ****

也就是,擴展方法跟類的方法沖突時候,編譯使用不會報任何錯誤,這時候以類的方法優先級最高,這時我們使用類的方法,而不是擴展方法。

分析:

我們把上述兩組代碼編譯後,再反編譯成IL,我們就可以看到,實際上,擴展方法在IL層上是不存在的。

擴展方法實際是編譯器調用某個類的某個方法的時候,先去這個類找,如果有這個方法,則就調用;如果找不到,根據引用的命名空間,再去找擴展方法(靜態類的靜態方法)。找到,就使用,找不到當然就編譯錯誤了。

根據這個分析結果,我們就可以理解上述問題處理的結果了。

情況二: 擴展方法的嵌套

比如我們有如下擴展方法。


namespace Hongjun.Guo 

static class MyExtensionMethods 

public static int Test01(this int i) 

return i * 3; 


public static int Test02(this int i) 

return i + 5; 



下面是調用范例:


static void Main(string[] args) 

int mm = 7; 
Console.WriteLine(mm.Test01().Test02()); 
Console.WriteLine("*****"); 
Console.WriteLine(mm.Test02().Test01()); 

Console.WriteLine("*****"); 

Console.WriteLine(MyExtensionMethods.Test02(MyExtensionMethods.Test01(mm))); 


Console.ReadLine(); 

問,調用的顯示結果是何值?

答案: 依次顯示: 26,36,26

分析:

mm.Test01().Test02()

這行代碼編譯後相當於如下代碼:

MyExtensionMethods.Test02(MyExtensionMethods.Test01(mm))

這兩行代碼在編譯後的IL中是完全一樣的。

 

 

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