2014-10-16 42 views
1

我遇到了一個我無法弄清楚的問題。我有一個提供方法簽名的接口。這個方法接受一個字符串,並返回一個布爾值。C#如何避免泛型將<T>方法推入與非泛型方法的簽名衝突?

該接口然後由一個抽象類實現,該類使用泛型類型T參數來定義接口函數的重載版本。這個重載的方法需要一個T並返回一個布爾值。同樣,接口方法被抽象出來以便由具體類而不是抽象實現來實現。

當具體類爲字符串T提供一個字符串時,我遇到了一個問題,因爲它似乎會導致接口方法簽名和抽象方法簽名之間的某種衝突。我試着尋找解決方案,但是我的谷歌搜索失敗了。

我編譯時收到以下錯誤消息:

錯誤2 'FooBarTest1.StringFoo' 不實現繼承抽象構件 'FooBarTest1.AFoo.Bar(字符串)' 的Program.cs 41 18 ConsoleApplication1

錯誤3繼承的成員'FooBarTest1.AFoo.Bar(string)'和'FooBarTest1.AFoo.Bar(T)'在'FooBarTest1.StringFoo'類型中具有相同的簽名,因此它們不能被重寫ConsoleApplication1 \ Program.cs 43 30 ConsoleApplication1

除了改變一個方法名稱之外,還有一個簡單的方法嗎? (示例代碼如下)

namespace FooBarTest1 
{ 
    public class Program 
    { 
     static void Main(string[] args) 
     { 
      Foo f = new Foo(); 
     } 
    } 

    public interface IFoo 
    { 
     bool Bar(string foo); 
    } 

    public abstract class AFoo<T> : IFoo 
    { 
     public abstract bool Bar(string foo); 
     public abstract bool Bar(T foo); 
    } 

    public class IntFoo : AFoo<int> 
    { 
     public override bool Bar(string foo) 
     { 
      return true; 
     } 

     public override bool Bar(int foo) 
     { 
      return Bar(foo.ToString()); 
     } 
    } 

    public class StringFoo : AFoo<string> 
    { 
     public override bool Bar(string foo) 
     { 
      return true; 
     } 
    } 
} 
+2

我肯定會改變方法的名字之一 - 如果沒有其他的清晰度。如果某人*創建了一個'AFoo ',並且他們調用Bar(「hello」)',那麼您希望它綁定哪個重載?他們會期待同樣的行爲嗎?如果您重新命名一種避免碰撞的方法,生活會更簡單。 – 2014-10-16 21:58:54

回答

0

您將不得不重新命名方法(或以其他方式更改簽名)。問題是如果T的類型爲String,則兩個Bar方法發生衝突。換句話說,當T是一個字符串時,您不再重載該方法 - 您正在複製該方法,這是一個錯誤。

要問的一個問題是「Bar的字符串實現與泛型實現有什麼不同(特別是在泛型類型是字符串的情況下)?」如果答案是「它們與......不同」,那麼改變名稱以反映不同的行爲應該是有意義的。

如果實現是相同的,那麼實現中的邏輯應該處理這種情況,並且您只需要一個具有該簽名的方法。換句話說,你可以用字符串參數保留實現,然後檢查方法內部的T的類型,以便在需要時執行其他操作。

否則,如果你不想重命名或刪除其中的一個,你可以這樣做:

public abstract class AFoo<T> : IFoo 
{ 
    // Change the signature without renaming 
    public abstract bool Bar(string foo, string baz); 
    public abstract bool Bar(T foo); 
} 
0

是的,有一種方法,以避免更改方法名。使用顯式接口實現(見https://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx)如下:然後

public abstract class AFoo<T> : IFoo 
{ 
    // Change the signature without renaming 
    abstract bool IFoo.Bar(string foo); 
    public abstract bool Bar(T foo); 
} 

AFoo將用作:

AFoo<String> af = new Implementation(); 
//Call generic method 
Console.Writeline(af.Bar("Hello world!")); 
//Call interface method 
Console.Writeline(((IFoo)af).Bar("Hello world!"));