C#泛型类型引起歧义 [英] C# Generic Types Cause Ambiguity

查看:146
本文介绍了C#泛型类型引起歧义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建一个自定义泛型类:

 类窗口小部件< T1,T2和GT; 
{
...
公共BOOL酒吧(T1型1)
{

}
公共BOOL酒吧(T2 TYPE2 )
{

}

}

以下行,当然,创建一个暧昧电话编译错误:

 窗口小部件< INT ,INT>美孚=新的窗口小部件< INT,INT>(); 
...
Foo.Bar(5);
...



有没有解决这个办法吗?有没有办法,我可以沿着线把条款,​​其中子:typeof(T1)= typeof运算(T2)!,或任何方法,使这项disambiguous? 。最好INT,INT将是可用的,但它不是manditory



更新:



其实,我对我自己发现了一个可接受的解决方案(我)这个问题,对于那些有兴趣谁

 类窗口小部件< T1,T2和GT; 
{
...
公共BOOL酒吧(对象o)
{
如果(o.GetType()== typeof运算(T1))
{

}
如果(o.GetType()== typeof运算(T2))
{

}
}

}


解决方案

有没有办法,我可以沿着哪里!子:typeof(T1)= typeof运算(T2)的线把条款




您可以让您的构造函数在运行时抛出异常。但是没有办法,以防止在的编译时间的这种情况。




什么办法,使这个明确的?




您应该改变你的方法名,使他们不冲突。这是迄今为止做的最安全和最简单的事情。



在事实上,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



另外请注意,编译器的将会的从创建一个类型阻止你这样的,它实现了两个的接口的可能是正在建设中相同。这是非法的:

 类C< T,U> :的IFoo<吨>中的IFoo< U> {...} 



因为你可以再构造 C< INT,INT> ; 和CLR就没有办法知道哪些方法对应的接口插槽



但我似乎已经有所题外话。回到主题。



你是这个班的创造者,你可以选择让他们受到任何可能的建设不同于重命名酒吧的方法。假设你固执地选择不。这有什么,如果他们想使你的不幸类的用户的可以做窗口小部件< INT,INT> ?是的,其实,还有就是,因为KVB指出。的他们可以定义扩展方法是做正确的事



 公共静态无效BarTheFirst< A,B> (此窗口小部件< A,b> W,A一)
{
w.Bar(一);
}

公共静态无效BarTheFirst< A,B>(此窗口小部件< A,B> W,B B)
{
w.Bar(二) ;
}



重载完成的在编译时间的,并在编译的时候,我们都知道的是,第一个要求接受一个A的酒吧,和第二个电话,需要一个B的酒吧。我们不重新做在运行时重载,所以现在你可以说

 窗口小部件< INT,INT> W =什么; 
w.BarTheFirst(5);
w.BarTheSecond(10);

和它会做正确的事情。


I am creating a custom generic class:

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

The following lines, of course, creates an ambiguous call compile error:

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

Is there any way around this? Is there a clause that I can put along the lines of "where : TypeOf(T1) != TypeOf(T2)", or any way to make this disambiguous? Preferably int,int would be available, but it is not manditory.

Update:

I actually on my own discovered an acceptable solution (for me) to this problem, for those who are interested

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

解决方案

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

You could make your constructor throw an exception at runtime. But there's no way to prevent this situation at compile time.

Any way to make this unambiguous?

You should change the names of your methods so that they do not collide. That is by far the safest and easiest thing to do.

In fact, IIRC the CLR reserves the right to fail to create a type that produces an ambiguity in method signatures like that. (Obviously our implementation actually does succeed, but you are treading on very thin ice when you pull these sorts of shenanigans.)

Doing this kind of thing is a really, really bad idea because it can get you into all sorts of trouble. Here's an example of how things go terribly wrong:

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

Also note that the compiler will stop you from creating a type such that it implements two interfaces that could be identical under construction. This is illegal:

class C<T, U> : IFoo<T>, IFoo<U> { ... }

because you could then construct C<int, int> and the CLR would have no way of knowing which methods corresponded to which interface slots.

But I seem to have digressed somewhat. Back on topic.

Since you are the creator of this class, you can choose to rename your "Bar" methods so that they are different under any possible construction. Suppose you stubbornly choose not to. Is there anything that the user of your unfortunate class can do if they want to make Widget<int, int>? Yes, actually, there is, as kvb points out. They can define extension methods that do the right thing.

public static void BarTheFirst<A, B>(this Widget<A, B> w, A a)
{
    w.Bar(a);
}

public static void BarTheFirst<A, B>(this Widget<A, B> w, B b)
{
    w.Bar(b);
}

Overload resolution is done at compile time, and at compile time all we know is that the first one calls the Bar that takes an "A", and the second one calls the Bar that takes a "B". We do not re-do overload resolution at runtime, so now you can say

Widget<int, int> w = whatever;
w.BarTheFirst(5);
w.BarTheSecond(10);

and it will do the right thing.

这篇关于C#泛型类型引起歧义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆