程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#3.0新體驗(二)

C#3.0新體驗(二)

編輯:關於C#

前言:

學習除了要堅持不懈,還需要有好的方法!總結整理自己學習 的資料能使得所學的內容條理清晰,查找回顧也很方便!俗話說的好:“ 好記性不如爛筆頭”;以前很多知識都是看過後,過一段時間就忘記,時 間花下去了,但效果甚微;看的多,但雜而不精;這些都是沒有做筆記,沒有深 入學習而導致的時間與精力的浪費,因此每個研究課題,都要好好整理資料,做 一個系列的研究!

三.擴展方法 (續接上一編)

擴展方法定義如 下:

public static class Extensions{
    public static void Foo(this string s) {
        …
     }
}
使用:
    String s=“Hello,World”;
    s.Foo();

我們以 前會對一些參數、對象進行某些處理,而寫一些獨立方法來封裝這些處理語句; 這些方法為了方便重用,可能會寫在一些公共類裡供大家調用,例如:

定義一個公共方法計算每天有多少分鐘,
public class PublicCenter
{
    //傳入參數為天數
    public long GetDaysMin(int pDays)
    {
        return pDays * 24 * 60;
    }
}
外部使用調用:
int days = 3;
PublicCenter pCenter = new PublicCenter();
int minutes = pCenter.GetDaysMin(days);

我想大家對上面這段代 碼的使用都非常熟悉,以前這樣處理的情況非常的多!現在我們看看用擴展方法 來處理會是怎麼樣;

定義一個靜態類的靜態方法計算每天有多少 分鐘(注意必須是靜態)
public staticclass PublicCenter
{
    //傳入參數為天數(注意this關鍵字必不可少)
     public staticlong GetDaysMin( this int pDays)
    {
         return pDays * 24 * 60;
    }
}
外部使 用調用:(注意靜態類必須同在一個命名空間,或添加引用,這個大家應該也知 道的(啰嗦))
int days = 3;
//當我們在所以int類型的變量後按 下".",就會智能提示出這些自己寫的擴展方法GetDaysMin()。
int minutes = days.GetDaysMin()

大家可以看出擴展方法的 本質為將實例方法調用在編譯期改變為靜態類中的靜態方法調用。

MSDN 中對擴展方法的定義是:擴展方法使您能夠向現有類型“添加”方法 ,而無需創建新的派生類型、重新編譯或以其他方式修改原始類型。

為 什麼使用擴展方法?

第一.使用方便:定義好某個類型的擴展方法後,只 要是在這個類型後面點一個“.",就可以找到所有的擴展方法;而不 用像以前先要找到方法所放的那個類,然後用通過調用該類的方法來實現;(很 多時候,公共類庫和實際調用是不同開發人員開發的,往往需要調用的人員不知 道哪個類有哪些功能可以使用,這個在公共類庫比較龐大的時候很麻煩)

第二.擴展方便:可以很方便的擴展底層類庫,接口,第三方類庫(控件 ,插件)等等,在上面添加我們需要的功能;而不需要我們重新修改這些底層類 庫,控件等(有很多時候這些東西我們根本沒有辦法更改,例如第三方提供的, 非開源的);

擴展方法幾種使用情況:

1.傳遞參數:

public static class Extensions{
    //this必須放 第一個位置,後面傳遞參數類型沒有限制
    public static void Foo(this string s,string pName) {
        …
    }
}
使用:
    String s=“Hello,World”;
    s.Foo ("maotin");

2.擴展方法的優先級:

注意擴展 方法的優先級:現有實例方法優先級最高,其次為最近的namespace下的靜態類 的靜態方法,最後為較遠的namespace下的靜態類的靜態方法。

//下面這 段從網友博客中拷貝修改(原文地址: http://blog.joycode.com/ghj/archive/2007/06/06/103872.aspx)

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

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