2010-08-27 77 views
3

最近我一直在使用擴展方法來幫助我的代碼更流利,但是我一直在遇到不能限制我以我想要的方式創建的功能的暴露情況。爲什麼擴展方法類不能嵌套是否有很好的理由?

說我有一些像這樣的代碼(完全由爲例):

var liveSet = allitems.Where(x => x.Status == Status.Live).Select(x => x.Name); 
var deadSet = allitems.Where(x => x.Status == Status.Dead).Select(x => x.Name); 
var zombieSet = allitems.Where(x => x.Status == Status.Neither).Select(x => x.Name); 

我想使這更流暢,並停止重複自己:

var liveSet = allitems.SelectNameWhere(x => x.Status == Status.Live); 
... 

但我認爲這是一個輔助方法,而不是一個真正的擴展,所以我想限制它的使用方式,就像我可以使用私有方法一樣:

//In the same class 
private static IEnumerable<string> SelectNameWhere(
        this IEnumerable<Element> items, 
        Func<Element, bool> predicate) 
... 

不幸的是我不能這樣做,因爲包含擴展方法的類必須是靜態的。好吧,不是世界的盡頭,我將嵌套一個私有的靜態類來保存這個方法......當然,我也做不到這一點,所以我沒有把這個方法暴露在至少一個內部層面上,或刪除我的代碼漂亮,流暢,自然:

var liveSet = SelectNameFrom(allItems, x => x.Status == Status.Live); 
... 

在那裏你可以聲明一個擴展方法,這些限制似乎相當任意的給我,但我認爲他們有良好的邏輯或技術的原因。如果是這樣,他們是什麼?

+1

不能對這個問題的技術細節發表評論。但它看起來像是在試圖將功能拉大到不屬於那裏的擴展方法。通過存儲庫實現這些示例,並且問題消失。擴展*應該是全球性的。需要鎖定他們的訪問是一個非常糟糕的代碼味道imho。 – fearofawhackplanet 2010-08-27 10:39:47

+1

我同意在嵌套類中聲明「本地」擴展方法通常很有用。或者,你可以聲明它們在一個單獨的命名空間,所以它們不會出現在任何地方 – 2010-08-27 10:44:38

+0

我同意應該有一種方法來限制基於類(不只是命名空間)的擴展方法的範圍。 – Vaccano 2012-05-16 21:53:16

回答

3

擴展方法分類不嵌套的主要原因是爲了讓編譯器更容易找到它們(同樣的原因導致它們被限制爲靜態類)。現在,編譯器必須掃描名稱空間下的所有靜態類才能找到這些方法。如果允許在所有類中嵌套或使用它們,那麼編譯器的工作就會困難得多。此外,這可能會導致名稱衝突。因爲我不知道答案

例如:

public static class Foo 
{ 
    public static void DoStuff(this object param) 
    { 
    } 
    public static class Bar 
    { 
     public static void DoStuff(this object param) 
     { 
     } 
    } 
} 
0

您不想公開擴展方法的事實應該清楚地表明您的函數不應該是擴展方法。擴展方法旨在以更友好的方式公開類型中的現有功能。

+1

我的示例不是以更友好的方式公開現有功能嗎?如果它是在一個單獨的公共擴展類中,我不相信任何人會聲稱它不是擴展方法的有效用法。這只是一個擴展方法,我不希望在使用它的類之外混淆我的智能感知。 – 2010-08-27 12:52:48

+0

你是對的,它是擴展方法的有效用法。但是您現在想要改變擴展方法的實現方式,以適應IDE的便利性,這不是一個需要它的好理由。畢竟,您可以使用記事本編寫C#代碼。 – jvanrhyn 2010-08-27 18:06:18

相關問題