2015-08-24 71 views
3

我試圖編寫代碼,而且我總是返回對象本身,因此我可以繼續鏈接。像這樣如何在C中鏈接方法時進行轉換#

object.SetThis().SetThat().SetThisThirdThing().setThisFourthThing(); 

我在我的所有方法中都返回了這個值,所以我可以繼續這樣做。但我的一個方法是我在我的基類中創建的,當然這會返回基類。

因此,而不是public MyClass SetThat()它返回public SuperClass SetThat()。因爲它返回SuperClass而不是MyClass我不能撥打SetThisThirdThing(),因爲基類不知道它。

那麼我該如何施展才能保持鏈條?什麼是語法?我試圖

object.SetThis().(MyClass)SetThat().SetThisThirdThing().setThisFourthThing(); 

還是有一種方法,使一個超類方法返回時,從子類叫做子類,而不必重寫它在所有子類?

這是所有子類共有的東西之一,所以如果我能以某種方式規避這種情況而不必在我的所有子類中重寫它,那將是非常好的。

+1

你爲什麼不只投的第一個元素? ((MyClass)對象).SetThis()。SetThat() –

+4

作爲參考,「點」更通常稱爲「流暢接口」。 – Mitch

+0

@Mitch不知道這是真的,流暢的接口實際上只是[方法鏈接]的一個子集(https://en.wikipedia.org/wiki/Method_chaining) – DavidG

回答

4

有沒有一種方法,使從子類調用時超類方法返回的子類,而不必重寫它在所有子類?

你可以使超類一般?

public class SuperClass<T> where T: SuperClass<T> 
{ 
    public T SetThis() 
    { 
     .... 
     return (T)this; 
    } 
} 

public class SubClass : SuperClass<SubClass> 
{ 
} 

請注意,這不是100%保證,因爲你也可以這樣做:

public class EvilSubClass : SuperClass<SubClass> 
{ 
} 

符合該通用的約束上,但現在的SetThis()返回類型爲​​,而不是EvilSubClass

+0

我認爲這是一個很好的解決我的困境的方案。我會試試這個。 – Hafax

+0

這似乎很好,所以我打算接受它作爲答案。但是現在我遇到了一個問題,我想將泛型超類作爲方法參數。我不能只使用公共MySuperClass addThis(MySuperClass theObject),因爲它說「名稱MySuperClass在當前上下文中不存在」?如何解決這個問題? :) – Hafax

+0

我會問,作爲一個單獨的問題 - 但廣泛地說,你可以將非泛型方法拆分成非泛型超類。但這取決於你打算如何使用超類。如果仿製藥打破了所有下游流程,那麼過載可能就是要走的路。 –

1
var obj = ((MyType)myObject.SetThis()).SetThat(); 

P.S你應該避免這樣做,因爲讀取會變得非常混亂。

+0

爲什麼一個人應該避免這種情況。 – MrPaulch

+0

@MrPaulch認爲這是顯而易見的:) – Hristo

+0

明顯的你,也許對我很明顯。但對每個人都不明顯。這只是一個建議,以改善您的答案! – MrPaulch

0

只需使用括號:

(MyClass)(object.SetThis().SetThat()).SetThisThirdThing().setThisFourthThing(); 

我不知道爲什麼object是存在的,但你可以放心地將其刪除。

(MyClass)(SetThis().SetThat()).SetThisThirdThing().setThisFourthThing(); 
+0

對象只是在那裏顯示我是在一個物體上做的。也可以是myObject.SetThis()。SetThat() – Hafax

+0

'object'是變量名稱。但我確實喜歡附加的括號,這使得它非常明顯地表明正在播放的內容。 – juharr

1

嘗試這樣的:

((MyClass)object.SetThis().SetThat()).SetThisThirdThing() 
+0

這不起作用 - 在這個表達式中,SetThreadThing()的返回值將被轉換爲MyClass。它將與'(MyClass)object.SetThis()。SetThat()。SetThisThirdThing()''相同。 – Glorfindel

+0

@Glorfindel你說得對,我的錯。編輯我的答案。 – Nevca

1

要轉換(子)表達式,您需要將類名稱放在前面(並使用括號)。

((MyClass)obj.SetThis().SetThat()).SetThisThirdThing().setThisFourthThing(); 

(注意:object是一個保留字,所以你不能把它作爲一個變量名)

另一種方法是使用as關鍵字:

(obj.SetThis().setThat() as MyClass).SetThisThirdThing().setThisFourthThing(); 

注意如果setThat()未返回MyClass,則此行爲將有所不同; 第一個版本將拋出一個InvalidCastException,第二個版本爲NullReferenceException,因爲as返回null如果轉換不可行。

+1

但是,如果使用'as MyClass',則可以獲得空引用異常。 – DavidG

+1

在相同的情況下,如果您使用直接轉換,您只會得到一個不同的異常 – Jonesopolis

0

無需修改類,你也可以寫一個擴展方法As這樣

public static T As<T>(this MyBaseClass obj) where T : MyBaseClass 
{ 
    return (T)obj; 
} 

-

用法將類似於此

new MyChildClass().SetBase().As<MyChildClass>().SetThis(); 
0

爲什麼不能做到像這個?一個簡單的方法Cast幫你將它轉換回正確的類型......

class Program 
{ 
    static void Main(string[] args) 
    { 
     var obj = new MyClass(); 
     //obj.SetThis().SetThat().SetThisThirdThing().setThisFourthThing(); // Compile error 
     obj.SetThis().SetThat().Cast<MyClass>().SetThisThirdThing().setThisFourthThing(); 
    } 
} 

class SuperClass 
{ 
    public SuperClass SetThat() 
    { 
     return this; 
    } 

    public T Cast<T>() where T : SuperClass 
    { 
     return (T)this; 
    } 
} 

class MyClass : SuperClass 
{ 
    public MyClass SetThis() 
    { 
     return this; 
    } 

    public MyClass SetThisThirdThing() 
    { 
     return this; 
    } 

    public MyClass setThisFourthThing() 
    { 
     return this; 
    } 
}