2010-02-23 66 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超载。静态方法不需要是扩展方法,但我认为它更清晰一些。