2012-04-04 72 views
9
public static class MyClass 
{ 
    public static void Print<T>(this T theObject) 
    { 
     Console.WriteLine("The print output is " + theObject.ToString()); 
    } 
} 

在給定的I類所指定的通用的類型經由this關鍵字延伸。由於我在編譯時間之前推遲了類型的定義,intellisense(以及其他任何涉及的)如何知道我正在擴展的類型? C#是否默認爲頂層System.Object創建通用擴展方法時,我們正在擴展什麼?

+2

這是什麼都與LINQ呢? – BoltClock 2012-04-04 15:33:08

+0

@ BoltClock'saUnicorn linq中的流暢sytnax基於擴展方法。 – 2012-04-04 15:48:35

+2

@RoyiNamir LINQ基於擴展方法的事實並不會使所有與LINQ相關的擴展方法相關。 – Servy 2012-04-04 15:50:15

回答

1

因爲我已經延遲了類型的定義直到編譯時間,intellisense(以及其他涉及到的)如何知道我正在擴展的類型? C#是否默認爲頂層System.Object?

那些說這是System.Object的延伸是錯誤的。首先,這種方法不會將值類型輸入框,但在System.Object上定義的擴展方法將會。

你定義的擴展方法是一般參數擴展方法。它可以應用於任何類型爲的有效的通用類型參數

如果你沒有考慮過以下列方式擴展方法,這可能會幫助你瞭解他們更好一點。擴展方法只是語言規範讓我們逃避的一個技巧。擴展方法實際上只是靜態類中的靜態方法,我們可以將它們稱爲實例方法。所以

static class Foo { 
    public static void M(this object obj) { } 
} 

只是靜態類中的靜態方法。你可以這樣調用它:

Foo.M(obj); 

,但我們可以把它喜歡它是一個實例方法:

obj.M(); 

因此,當你有一個通用的擴展方法,停了一分鐘,想想作爲一個靜態類的靜態方法

static class Foo { 
    public static void M<T>(this T obj) { } 
} 

你可以這樣調用它:

object obj; 
Foo.M(obj); 

,或者你可以這樣調用:

obj.M(); 

有到你寫的編譯器沒有區別。

所以,現在你想它作爲一種常規的泛型方法。但是當你從這個角度思考它時,你明白編譯器會讓你在任何有效的泛型類型參數類型上調用這個方法。因此,你現在明白了爲什麼它可以被認爲是任何有效的泛型類型參數的擴展方法。

+0

+1這是有用的信息要知道。這個技巧是如何工作的?我們是否假設這是句法糖?換句話說,編譯器是否簡單地將'obj.M()'的調用轉換爲'Foo.M(obj)'? – 2012-04-04 18:11:43

+1

是的,它只是語法糖。請參閱語言規範的7.6.5.2。特別是,在該部分中創建了「該方法調用然後作爲靜態方法調用進行處理」的語句。 – jason 2012-04-04 18:19:37

+0

@jason 95%關於sytatic糖的信息和5%關於'我們在擴展什麼'請提供**證明**我們沒有擴展system.object。 – 2012-04-05 03:08:21

3

是的,這是System.Object除非你添加一個類型約束。

+1

@RoyiNamir:通用**參數**('Print ()')可以,而不是約束('where T:SomeType')。 – 2012-04-04 15:38:05

+0

@GeorgeDuckett我的意思是你不必添加類型。 T – 2012-04-04 15:40:08

+0

在對象上擴展與在所有有效的泛型類型參數的所有類型上擴展是不同的。它不是對象的擴展。 – jason 2012-04-04 18:10:45