2010-07-06 69 views
8

在你開始指向我重複之前,只要知道我已經閱讀過關於擴展方法的幾乎所有帖子。我只是試圖扮演魔鬼的辯護者一分鐘來考慮替代我的工作觀點。什麼時候應該避免擴展方法?

最近我正在研究一個項目,並且需要一個方法作爲接口的基礎。所以我建議我們寫一個擴展方法,它被擊落。說它增加了調試複雜性和難度。

我當然爭辯說,並找到所有的精彩帖子,顯示爲什麼要使用擴展方法的原因。不要忘記很多.net框架使用它們。我們最終沒有使用它,因爲我被團隊推翻了。

但是後來讓我想到了,有沒有時間可以使用擴展方法,但不應該?

我真的想不出任何,但我想我會張貼在這裏,看看有沒有人可以想到爲什麼他們不應該使用任何其他原因。

+0

檢查這篇文章... http://www.vitalygorn.com/blog/post/2008/01/Extension-Methods---Extension-or-Confusion.aspx – Luiscencio 2010-07-06 21:09:21

+0

@Luiscencio感謝您的文章。這有點長,所以我會在幾分鐘後給它閱讀併發回。但它看起來像我想知道的東西。 – spinon 2010-07-06 21:12:44

回答

5

任何時候當你有一個函數「一般適用」到一個特定類型的對象,無論其狀態如何,擴展方法是一個不錯的選擇。

比如,今天我添加了兩個新的擴展方法,我們的代碼庫:

public static XElement ToXElement(this XmlElement element) { } 

public static XmlElement ToXmlElement(this XElement element) { } 

上述這些問題都,一般來說,就不管他們延長實例的狀態,或者我們所處的各類有效使用它。

如果您的方法不符合該條件,則應將其移至更接近上下文的幫助器方法,其中特定情況始終爲真或易於檢查。

例如,開發人員,最近被任命這是一個擴展方法:

public static bool ParseYesNoBool(this string input) { } 

這裏有兩個問題:第一,這將出現在應用程序中的所有字符串,即使字符串的數量,其可能曾經是這種情況的候選人非常小。所以我們違反了第一條規則,因爲無論狀態如何,它都沒有用。同樣,但其次,此功能的使用者僅限於一個特定連接器到外部系統的單個解析器。因此,將特定於實現的功能提升爲通用名稱空間是沒有意義的。這被降級爲解析器中的輔助方法。

就可讀性和調試而言,這對於任何合理技能水平的開發人員來說都是不正確的。

+0

我和一個有擴展名的大文件的人一起工作,其中大多數都是特定的。我幾乎不得不開始採取憤怒管理類... – ChaosPandion 2010-07-06 21:17:28

+0

@anon爲什麼DV? – 2010-07-06 21:26:42

+0

這些都是他們應該和不應該使用的兩個很好的例子。我已經看到類似的情況,其中特定於對象的功能被添加到clr對象。他們正在檢查類型中特定於域對象的規則,並希望將擴展方法添加到該類型中以使其更容易。 我想我還有另外一個關於SO的問題,我會發布,而不是試圖將它全部納入評論中。另外使它可供搜索以供將來參考。 – spinon 2010-07-06 21:37:09

0

我會說你應該避免他們,因爲「他們沒有使代碼的意圖更清楚」。當然,某些代碼(或代碼風格)是否「更清晰」,在人們之間差異很大,因此幾乎沒有用處。 (我有一位老闆說我們應該避免使用接口,因爲他們讓代碼「太複雜而難以理解」)

+0

我只是想知道你怎麼可能有一個可能是壞的情況。我猜如果你把那些與類或接口本身毫無關係的方法作爲一種擴展方法,那將是其中一種情況。 p.s.你的老闆聽起來像一個真正的OOP大師:P – spinon 2010-07-06 21:14:20

1

通常,如果您控制程序集的源代碼並添加方法不會導致任何問題打破現有代碼的變化(如果例如LINQ沒有通過擴展方法實現,則會發生這種情況),最好添加一個常規方法。

1

This discussion關於擴展方法的框架設計Guildelines部分包含一些很好的建議。我認爲您的場景的相關部分是:

爲了提供與每個接口實現相關的幫助程序功能,如果所述功能可以用核心接口編寫。

如果您提出的使用方法未通過該測試,則應該將其擊落。

+0

我會看看我是否可以挖掘場景並在此發佈修改後的解釋。 – spinon 2010-07-06 21:15:02

0

擴展方法使您能夠將方法「添加」到現有類型,而無需創建新的派生類型,重新編譯或以其他方式修改原始類型。

任何時候你打破功能的意圖和設計,我會建議重新考慮使用擴展方法。如果您不想使用擴展方法,請參閱以下幾種情況:

1)更改對象模型以允許使用擴展方法:要在其上創建擴展的類是抽象類。這將要求您讓每個繼承類都是自己的擴展版本,或者從類中移除抽象。無論哪種方式,您都在更改對象模型以使用擴展方法。

2)忘記Decorator Pattern您爲類創建的擴展方法的數量超過三個。我發現組織/溝通和維護裝飾對象的域/對象模型比使用擴展對象更容易。然而,相反的情況也是如此:如果裝飾對象的方法少於四個,我會在我的項目中找到很多幾乎「空」的對象。

3)私有函數:私有函數用於修改(創建,刪除等)對象,擴展方法用於使用類型,非常像結構。如果你發現擴展名被分配給另一個類型的實例,那麼它可能不應該在擴展名中。

相關問題