2011-08-23 64 views
7

我知道C#擴展方法必須是靜態的。我不明白的是爲什麼這些擴展不能在非靜態類或通用類中定義?爲什麼必須在靜態類中定義C#擴展方法?

更新:我對這個設計決定背後的原因感興趣。

+0

我在問這個問題之前全面搜索靜態類的案例,我還沒有找到你所說的答案。順便說一下,這不是完全相同的問題,我的答案沒有在該文章中找到。 – Mehran

+0

這是一個*精確*重複的「爲什麼不可能在泛型靜態類中聲明擴展方法?」。 –

+0

這不是重複的。而不是所謂的雙重問題中的一個更具體的問題。 –

回答

5

這更多的是比回答的觀察,但是...

當你調用一個實例方法,對您所呼叫被壓入堆棧作爲第一個參數的對象的引用您的方法調用。第一個論點是「這個」,並且是隱含的。

當你定義一個擴展方法時,你明確地定義了一個「this」作爲第一個參數。

有沒有可能是方法決議將是混亂的,如果你能定義擴展方法和在同一類實例方法,即定義具有相同名稱的方法,並在實際上,相同的參數時,「這個」參數包括在內。

+0

這是一個很棒的觀察和一個合理的觀察。感謝分享它。 – Mehran

+0

也許,除了恕我直言,實際上應該是規則的一個很大的例外:應允許類或結構定義對其自身類型的成員進行操作的擴展成員,並且在結構的情況下,應該有可能「this」參數是按值或參考。這種擴展方法將允許不可變類類型在初始化方面更像值類型,並且允許在結構體增強器上使用正常的「方法」語法,而不會將其應用於只讀上下文。 – supercat

+0

@supercat如果你可以在一個類中定義一個擴展方法來作用於它本身,它不會是一個擴展方法嗎? –

1

因爲規範是這麼說的......現在可能有很好的理由爲什麼他們這樣寫規格。

他們不能在泛型類中聲明的原因很明顯:給定擴展方法的調用方式,你會在哪裏指定類的類型參數?

它必須是靜態類的原因不太明顯,但我認爲它是有道理的。靜態類的主要用例是將輔助方法組合在一起(例如,Path,Directory,ProtectedData ...),並且擴展方法基本上是輔助方法。例如,創建EnumerableQueryable的實例是沒有意義的。

+0

我明白規範說什麼。我很想知道爲什麼會做出這些設計決定。 – Mehran

+0

@Mehran,這正是我在我的答案中試圖解釋的......我沒有重複說明規範。 –

+1

公共擴展方法只對頂級靜態類有意義,但規則可能明智地允許在嵌套的私有或受保護類中聲明擴展方法,但條件是這些方法只能在可見的地方使用。例如,類'Foo '的代碼可以受益於能夠定義使用'Foo '私有類型的擴展方法。這樣的擴展方法在知道要使用什麼'T'的情況下不會有什麼問題,因爲唯一可以看到它的代碼將具有該類型。 – supercat

3

看看這片在.NET C#規格:

當一個方法的第一個參數包括該改性劑,該方法 被說成是一個擴展方法。擴展方法只能在非泛型非嵌套靜態類中聲明 。擴展方法的第一個參數 可以不包含 this以外的其他修飾符,並且參數類型不能是指針類型。

而這個片段來自Jon Skeet's answer

這不是很清楚,我爲什麼所有的這些限制是必要的 - 除了潛在的編譯器(和語言規範)的簡單性。 I 可以明白爲什麼將其限制爲非泛型類型是有意義的,但是我不能立即明白爲什麼它們必須是非嵌套和靜態的。我想 懷疑它使查找規則相當簡單,如果你不 不得不擔心當前類型等內包含的類型,但我敢說這是可能的。

相關問題