2010-10-29 90 views
15

假設您有兩個不同的C#類AB,雖然不是從同一基類派生,但它們共享某些方法的相同名稱。例如,兩個類都有一個connect和一個disconnect方法以及其他幾個。我希望能夠編寫一次適用於這兩種類型的代碼。處理具有相同方法名稱的不同類的C#代碼

這裏是我想要做的一個簡單的例子:

public void make_connection(Object x) 
{ 
    x.connect() ; 
    // Do some more stuff... 
    x.disconnect() ; 
    return ; 
} 

當然,因爲Object類沒有connectdisconnect方法,這並不編譯。

有沒有辦法做到這一點?

UPDATE。我應該從一開始就明確這一點:我只有A和B的DLL,而不是源。

+5

這是幾乎每個人如何學習的界面結構是多麼寶貴。在「得到它」之前,你確實需要找到他們有用的情況。 – 2010-10-29 05:46:55

回答

26

您可以使用一個接口來完成你想做的事情。

interface IConnectable 
{ 
    void Connect(); 

    void Disconnect(); 
} 

兩個AB應該實現IConnectable。然後使用IConnectable而不是Object作爲您的方法的參數類型,並且應該全部設置。

public void MakeConnection(IConnectable connectable) 
{ 
    connectable.Connect(); 

    // Do some more stuff... 

    connectable.Disconnect(); 
} 

編輯:既然你沒有源代碼,你有兩個選擇:

  1. 使用dynamic關鍵字,(如果你使用的是.NET的應用最大的解決方案4.0)
  2. 使用史蒂夫的使用鑄造和if/else報表
  3. AB創建包裝類,並有解決方案他們實現接口(或使用通用抽象基類爲他們)

例如:

class AWrapper : IConnectable 
{ 
    private A obj; 

    public AWrapper(A obj) 
    { 
     this.obj = obj; 
    } 

    public void Connect() 
    { 
     this.obj.Connect(); 
    } 

    public void Disconnect() 
    { 
     this.obj.Disconnect(); 
    } 

    // other methods as necessary 
} 

BWrapper有異曲同工之處,只是用的AB代替)

然後,你可以創建包裝並將它們傳遞到MakeConnection。這取決於你如何去做。根據你的情況,一種方法可能比其他方法更容易。

+3

在這裏迂腐,但類不*繼承*接口,他們*實現*他們。 – Phil 2010-10-29 05:30:44

+0

@菲爾:謝謝!固定。 – 2010-10-29 05:31:58

+2

如果您沒有A和B的源代碼,您如何讓A和B實現一個接口? – rlandster 2010-10-29 13:15:13

2

嘗試使用接口。

看一看interface (C# Reference)Interfaces (C# Programming Guide)

因此,像

public interface IConnections 
{ 
    void connect(); 
    void disconnect(); 
} 

public class A : IConnections 
{ 
    public void connect() 
    { 
     //do something 
    } 

    public void disconnect() 
    { 
     //do something 
    } 
} 

public class B : IConnections 
{ 
    public void connect() 
    { 
     //do something 
    } 

    public void disconnect() 
    { 
     //do something 
    } 
} 

public void make_connection(IConnections x) 
{ 
    x.connect(); 
    // Do some more stuff... 
    x.disconnect(); 
    return; 
} 
1

有你避免繼承鏈的OOAD概念「長期計劃的接口沒有實現」這讓層次

1您可以創建一個interfcae

interface IConnection 
{ 
    void Connect(); 
    void Disconnect(); 
} 

2 - 讓你的類實現這個接口,如下所示。

class A : IConnection 
{ 
    #region IConnection Members 

    public void Connect() 
    { 
     // your connect method implementation goes here. 
    } 

    public void Disconnect() 
    { 
     // your disconnect method implementation goes here. 
    } 

    #endregion 
} 


class B : IConnection 
{ 
    #region IConnection Members 

    public void Connect() 
    { 
     // your connect method implementation goes here. 
    } 

    public void Disconnect() 
    { 
     // your disconnect method implementation goes here. 
    } 

    #endregion 
} 

3-一旦你比,你可以讓你的函數接受IConnection的參數,如下圖所示的實施完成。

public void makeConnection(IConnection con) 
    { 
     con.Connect(); 
     con.Disconnect(); 
    } 

4-從客戶端代碼中,您可以傳遞實現IConnect接口的類的對象。

0

要麼你將不得不使用的接口(或基類)如圖扎克和astander,或你將不得不在使用前區分對象:

public void make_connection(Object x) 
{ 
    ((A)x).connect() ; 
    // Do some more stuff... 
    x.disconnect() ; 
    return ; 
} 
1

如果接口的解決方案是不可能的(例如你沒有源代碼),另一個不太有效的解決方案是使用反射。

+0

+1,以便在標準(界面)方法無法完成的情況下使用其他解決方案。 – VitalyB 2010-11-03 22:32:52

12

這將工作在C#4:

public void make_connection(dynamic x) 
{ 
    x.connect() ; 
    // Do some more stuff... 
    x.disconnect() ; 
    return ; 
} 
+2

+1是更安全的類型,你可以使用強類型的公共方法 - 'make_connection(A a)' - 委託給一個私有的動態方法。 – 2010-10-29 18:28:18

0

您也可以使用反射來調用方法

1

正如其他人所說,再保理使用的接口或使用動態的方法很可能是最優雅的方式。

如果這是不可能的,你可以將對象轉換爲你的類型。我建議使用as,然後檢查演員是否工作,如果有人用未能投射的類型調用此演員,則未經檢查的演員陣容會很危險。

E.g.如果類型AB都有一個方法叫DoSomething()那麼這將工作...

public static void CallDoSomething(object o) 
    { 
     A aObject = o as A; 

     if (aObject != null) 
     { 
      aObject.DoSomething(); 
      return; 
     } 

     B bObject = o as B; 

     if (bObject != null) 
     { 
      bObject.DoSomething(); 
      return; 
     } 
    } 

這是非常醜陋的,說實話......我真的嘗試並重構到接口。

0

你想要什麼叫做Duck Typing

維基百科:

鴨打字是動態類型的風格,其中對象的當前設置的方法和屬性決定了有效的語義,而不是從一個特定的類或實現其繼承具體界面。

C#4.0允許這一點,其他都表示,採用動態關鍵字

相關問題