2011-07-14 131 views
3

鏈方法在.NET中,你可以鏈方法返回一個值或使用無效。他們中的一個是「正確的方式」嗎?什麼是正確的方式在.net

所以你可以說

1)

Foo myFoo = new Foo(); 
myfoo.Bars = 
    myBars.DoSomethingCool(x) 
    .DoSomethingElse(y) 
    .AndSomethingElse(z); 

public static IList<IBar> DoSomethingCool(this IList<IBar> source, object x) 
{ 
    IList<IBar> result = //some fn(source) 
    return result; 
} 

在這種情況下,所有3種擴展方法需要返回的IList(用於myFoo.Bars類型)

,或者也可能是寫爲

2)

myBars.DoSomethingCool(x) 
.DoSomethingElse(y) 
.AndSomethingElse(z); 

public static void DoSomethingCool(this IList<IBar> source, object x) 
{ 
    //Modify source 
    source = //some fn(source) 
    //Don't return anything 
} 

在這種情況下,擴展方法返回一個空白,但這樣做在未來源對象的工作?

UPDATE西蒙在他的回答中是正確的,2)不會編譯。下面是如何重寫:

DoSomethingCool(myBars) 
.DoSomethingElse(myBars) 
.AndSomethingElse(myBars); 

myBars然後將在每個方法的調用內部進行更改,並且方法將返回void。

+3

鏈接方法好得多使得代碼更難調試,修改和維護。 –

+0

我不確定我是否理解它如何使調試,修改和維護變得更加困難。如果你把鏈接放在不同的行上,你可以在任何語句中設置一個斷點。鏈接使得它更容易表達意圖,這在我看來使維護更容易,而不是更難。 – John

+0

你的第二個例子不會編譯。 DoSomethingElse()在DoSomethingCool的返回結果上被調用,這是一個void。 – sisve

回答

0

1)獲得。西蒙正確地回答說,2)不會編譯,但他做了一個評論,所以我不能讓他信任回答。更新後的解決方案2)可以做所有事情的副作用,我想不出你爲什麼會想用靜態類型語言來做這件事。

有關鏈接的調試問題提出的觀點是值得考慮的,但我發現鏈接過濾時特別有用。

mybars.FilterByHasHappyHour()

BigGiantUtilityClass.GetBarsWithHappyHours(myBars) 
0

在這兩種情況下,你正在使用的擴展方法,返回一個對象,然後使用該對象作爲輸入到該鏈中的下一個方法。第二個例子接近Fluent Interface(但不完全)。我認爲在你的兩個例子中,關鍵區別是可變性。你想要修改原始輸入(第二個例子)還是不要(第一個例子)? 「正確的」答案取決於情況和背景。

+0

這就是問題:修改原始輸入還是通過副作用來操縱一件壞事是可以的? – John

+0

我不知道通過擴展方法修改這種方式肯定是一件「壞事」,儘管我可能會遠離它以避免混淆 - 至少我會命名方法來改變對象的類似「Change」的方法。 ..「或」修改...「。 按照慣例,幾乎所有的Linq擴展方法都在迭代器上運行,並提供了一個新的序列,而不是修改原來的序列。通過操作並返回最小公分母(迭代器),Linq擴展可以適應最廣泛的情況和目標對象。 – daveaglick

+0

但要記住的一點是,擴展方法與其他方法沒有區別,第一個參數只是隱式的而不是顯式的。這意味着,由於它在被操作對象的外部,所以該方法不能比其他任何訪問更容易訪問。如果原始對象不可變,那麼鏈中的方法也不能改變它。這意味着只要原始對象的接口設計得當,就不會有破壞封裝的危險。 – daveaglick

相關問題