今天早上在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中是完全一樣的。