2010-02-23 116 views
6

我創建一個自定義泛型類:C#泛型類型引起歧義

class Widget< T1, T2> 
{ 
    ... 
    public bool Bar(T1 type1) 
    { 
     ... 
    } 
    public bool Bar(T2 type2) 
    { 
     ... 
    } 
    ... 
} 

以下行,當然,創造一個模糊的通話編譯錯誤:

Widget<int, int> Foo = new Widget<int, int>(); 
... 
Foo.Bar(5); 
... 

有沒有解決這個任何方式?有沒有一個條款,我可以把「where:TypeOf(T1)!= TypeOf(T2)」,或任何方式使這種消除歧義?最好是int,int可用,但它不是必須的。

更新:

其實我對我自己發現了一個可接受的解決方案(我)這個問題,對於那些有興趣誰

class Widget< T1, T2> 
{ 
    ... 
    public bool Bar(object o) 
    { 
     if(o.GetType() == typeof(T1)) 
     { 
      ... 
     } 
     if(o.GetType() == typeof(T2)) 
     { 
      ... 
     } 
    } 
    ... 
} 
+0

我想知道什麼是真實世界的情況下... – user76035 2010-02-23 21:57:51

+0

在現實中它變成和無效的方法超載 – Perpetualcoder 2010-02-23 22:24:13

+1

@wwosik:帶有2個鍵的字典。 – 2010-02-24 16:28:49

回答

18

Is there a clause that I can put along the lines of "where : TypeOf(T1) != TypeOf(T2)"

你可以讓你的構造函數在運行時拋出異常。但是在編譯時間沒有辦法阻止這種情況。

Any way to make this unambiguous?

你應該改變你的方法的名稱,使它們不會相互碰撞。這是迄今爲止最安全和最容易做的事情。

事實上,IIRC CLR保留未能創建類似方法簽名的類型的權利。 (顯然,我們的實現確實成功了,但當你拉這些詭計時,你正在踩着非常薄的冰塊。)

做這種事情是一個非常非常糟糕的主意,因爲它可以讓你進入各種各樣的麻煩。這裏的東西怎麼去可怕的錯誤示例:

http://blogs.msdn.com/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx

http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx

還要注意的是,編譯器從創建一個類型阻止你這樣的,它實現了兩個接口這可能是相同的

+0

「實際上,IIRC CLR保留未能創建類似方法簽名中產生歧義的類型的權利。」真的嗎?如果是這樣的話,當你創建'Widget '時,C#編譯器不應該吐出一個警告(至少)嗎? – 2010-02-23 22:01:39

+0

嗯,它的確如此:請參閱OP:「模糊調用編譯錯誤」 – user76035 2010-02-23 22:03:31

+0

@wwosik:該錯誤用於方法調用。埃裏克正在談論CLR在這種類型被**創建的時候炸燬該程序**。實際上,當我想到它的時候,編譯器很難發現它在深層嵌套在通用方法中,比如外部程序集。 – 2010-02-23 22:06:16

5

給你的功能獨特的名字

0

這看起來像一個情況下,你會希望有一個基礎通用類

abstract class WidgetBase<T1> 
{ 

    public abstract bool Bar(T1 type); 
    ... 
} 

然後繼承你的實現

class WidgetA : WidgetBase<int> 
{ 
    public bool Bar(int type) 
    { 
     ... 
    } 
} 

class WidgetB : WidgetBase<int> 
{ 
    public bool Bar(int type) 
    { 
     ... 
    } 
} 
1

我跟別人說你應該改變你的類同意,這樣的碰撞不會發生(例如通過重命名方法)。但是,如果你沒有自己的類中,有解決方法:

public static class WidgetExtensions 
{ 
    public static bool Bar1<T1,T2>(this Widget<T1, T2> w, T1 t1) { return w.Bar(t1); } 
    public static bool Bar2<T1,T2>(this Widget<T1, T2> w, T2 t2) { return w.Bar(t2); } 
} 

您可以使用這些擴展方法調用適當的Bar超載。靜態方法不需要是擴展方法,但我認爲它更清晰一些。