2008-12-31 184 views
38

.NET中的擴展方法是什麼?什麼是擴展方法?



編輯: 我已經發布了一個跟進的問題在Usage of Extension Methods

+1

對於你的後續行動,請參閱下面的答案。 基本上你會創建擴展而不是使用繼承。 – 2008-12-31 17:47:01

+0

@湯姆安德森 - 所以創建擴展方法的決定主要基於對源代碼的訪問?我的情況是 – Developer 2008-12-31 17:49:54

+1

。 另一個實例很容易,而不是從System.Windows.Forms.Form繼承,然後添加方法,然後修改我的所有源以使用該基類,我只需編寫該擴展,現在所有表單都具有該擴展。 – 2008-12-31 17:52:37

回答

50

擴展方法允許開發新的方法添加到現有的CLR類型, 的公共 合同,而無需子類,或 重新編譯的原始類型。

擴展方法幫助混合的 靈活性的「鴨打字」支持 今天 動態語言中流行的性能和編譯時強類型語言 的 驗證。

參考:http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx

下面是一個擴展方法的一個樣品(注意第一參數的this關鍵字盈):

public static bool IsValidEmailAddress(this string s) 
{ 
    Regex regex = new Regex(@"^[\w-\.][email protected]([\w-]+\.)+[\w-]{2,4}$"); 
    return regex.IsMatch(s); 
} 

現在,上面的方法可以被稱爲直接從任何字符串,像這樣:

bool isValid = "[email protected]".IsValidEmailAddress(); 
然後

添加的方法也將出現在智能感知:

alt text http://www.scottgu.com/blogposts/extensionmethods/step1.jpg

至於用於擴展方法實際使用,您可以添加新的方法,一類沒有派生新類。

看看下面的例子:

public class Extended { 
    public int Sum() { 
     return 7+3+2; 
    } 
} 

public static class Extending { 
    public static float Average(this Extended extnd) { 
     return extnd.Sum()/3; 
    } 
} 

正如你所見,類Extending是加入一個名爲平均法Extended類。爲了得到平均,你叫average方法,因爲它屬於extended類:

Extended ex = new Extended(); 

Console.WriteLine(ex.average()); 

參考:http://aspguy.wordpress.com/2008/07/03/a-practical-use-of-serialization-and-extension-methods-in-c-30/

5

擴展方法的方式爲開發商的「附加」方法,他們無法控制的對象。例如,如果您想爲System.Windows.Forms對象添加一個「DoSomething()」方法,因爲您無法訪問該代碼,您只需爲該表單創建一個擴展方法以下語法。

Public Module MyExtensions 

    <System.Runtime.CompilerServices.Extension()> _ 
    Public Sub DoSomething(ByVal source As System.Windows.Forms.Form) 
     'Do Something 
    End Sub 

End Module 

現在您可以在表單中調用「Me.DoSomething()」。

總之,它是一種向現有對象添加功能而無需繼承的方法。

3

擴展方法是「編譯器把戲」,讓您可以模擬加方法到另一個類,即使你沒有它的源代碼。

例如:

using System.Collections; 
public static class TypeExtensions 
{ 
    /// <summary> 
    /// Gets a value that indicates whether or not the collection is empty. 
    /// </summary> 
    public static bool IsEmpty(this CollectionBase item) 
    { 
     return item.Count == 0; 
    } 
} 

從理論上講,所有集合類現在包括IsEmpty方法,如果方法沒有項目(前提是你已經包括定義上述類的命名空間),則返回true。

如果我錯過了任何重要的東西,我肯定有人會指出。 (請!)

當然,也有關於擴展方法的聲明(他們必須是靜態的,第一個參數必須由this關鍵字來preceeded,等等)的規則。

擴展方法實際上並不修改它們看起來正在擴展的類;相反,編譯器會破壞函數調用,以便在運行時正確調用該方法。但是,擴展方法正確顯示在具有獨特圖標的智能感知下拉列表中,並且您可以像正常方法一樣記錄它們(如上所示)。

注:擴展方法從未替代的方法,如果方法已經具有相同簽名存在。

1

下面是VB.Net中的示例;注意Extension()屬性。將其放置在項目的模塊中。

Imports System.Runtime.CompilerServices 
<Extension()> _ 
Public Function IsValidEmailAddress(ByVal s As String) As Boolean 
    If String.IsNullOrEmpty(s) Then Return False 

    Return Regex.IsMatch(email, _ 
     "^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$") 
End Function 
0

這個問題已經回答了,但我想補充一點,這是非常有用的,如果你有是另一個項目內的類型,你不想回到那個項目爲了添加一些功能。我們使用NHibernate併爲我們的數據持久層提供了一個項目,這些人員都希望保持清潔。爲了在這些對象上獲得更好的和可發現的附加方法,我可以使用擴展方法,它真的讓我的一天變得更加美好。

而且,因爲沒有其他人貼吧,這裏有關於它的MSDN一個很好的文章 - http://msdn.microsoft.com/en-us/library/bb383977.aspx

7

爲什麼我寫另外一個答案?

上述答案太複雜。我猜如果你需要問什麼是擴展方法,你不會真正知道什麼是(i)公共契約,(ii)CLR,(iii)類型,(iv)子類,( v)鴨打字等

讓我們保持它的簡單 - 擴展方法解釋

假如我有一隻狗。狗是一種「類型」的動物。所有的狗 - 類犬的所有動物 - 做某些事情:

  1. WagsTail
  2. 呼喊
  3. 震撼爪子等

的東西,狗可以「汪!」這些都是所謂的「方法」。

現在讓我們假設OO天堂的偉大程序員忘了給狗類添加一個方法。假設你想讓你家裏的所有狗做額外的事情:FetchNewspaper。

你要能夠說:

rex.FetchNewspaper(); // or 
wolfie.FetchNewspaper(); // or 
beethoven.FetchNewspaper(); 

......即使你沒有訪問源代碼。沃爾夫,雷克斯和貝多芬是你寵物家庭中的狗。

你最近怎樣才能讓你的狗做到這一點?

您將不得不重新編譯。但是你沒有源代碼!如果您沒有源代碼,則無法將該方法添加到代碼中的相關位置。

你唯一的解決方法是創建一個「擴展方法」。

創建擴展方法

(注意:在下面的第一個參數前面的「this」關鍵字):

public static void FetchNewsPaper(this Dog familyDog) 
{ 
    ConsoleWriteline(「Goes to get newspaper!」) 
} 

如果你想你的狗拿到報紙僅僅做到這一點:

Dog freddie_the_family_dog = new Dog(); 

freddie_the_family_dog.FetchNewspaper(); 

如果沒有擴展方法,那麼你就不能問Freddie_the_family_dog到FETC h報紙。

我們剛剛做了什麼?

我們增加了一個額外的方法,讓所有的狗都有能力取得報紙。

它是如何工作的?

你只是:(i)打電話給你的狗,和(ii)告訴他取紙。你不能做的就是說「取一張報紙」,而不指定你家裏的哪隻狗應該抓取。

我希望能幫到你。如果您在發表評論時仍有問題,我會盡我所能解釋。

0

我想我會添加一個更具概念性和較少依賴代碼的解釋。

想象一下福特公司正在推出施工線。您無法進入施工生產線,但您希望所有福特汽車能夠在汽車後部增加一個擾流板(展示時看起來更酷)。你打算怎麼做?在計算世界中,除非你有機會接觸到福特工廠的原始生產線,否則你不能只是把東西拉向福特。那麼現在你可以:輸入擴展方法。

現在你可以做這樣的事情:

Ford hilux = new Ford(); 

hilux.DisplayRearFoiler(); // you can now do this even though you don't have access to the Ford source code. 

你必須創建擴展方法。參考上面的答案。

0

我想根據密封類回答擴展方法。

假設你有一個密封類包含重要的方法。你現在想要爲它添加一個新的方法。假設這個類來自一個外部DLL,所以你不能添加一個新的方法。你會做什麼 ?

舉另一個例子。假設該類是由項目經理或安全專家構建在您的應用程序中的。只有獲得項目經理或安全專家的許可,才能編輯該課程。

您的解決方案可能是從此類中刪除密封關鍵字,並且 會在其他類中繼承它。然後在子類(繼承這個類)內部,你可以添加你的新方法。

但等待 - >您不能簡單地刪除密封關鍵字,因爲這可能會危及整個應用程序的安全性。我可以打賭你的PM或安全專家永遠不會以安全問題給你這個權限。

那麼在這裏可以做些什麼?

答案是擴展方法它可以添加在一個靜態類,你甚至不需要再觸摸密封類。

例子: -

sealed class MyData 
{ 
    private double D1, D2, D3; 
    public MyData(double d1, double d2, double d3) 
    { D1 = d1; D2 = d2; D3 = d3; } 
    public double Sum() { return D1 + D2 + D3; } 
} 

static class ExtendMyData 
{ 
    public static double Average(this MyData md) 
    { 
     return md.Sum()/3; 
    } 
} 

我加入了一個名爲平均到一個新的靜態類中的公共靜態方法。該方法的前面帶有'this'關鍵字的主類的參數。

現在要調用Average方法,我使用父級密封類的對象而不是子類。

MyData md = new MyData(3, 4, 5); 
double exAverage = md.Average(); 

希望你找到擴展方法有用。

相關問題