带约束的泛型方法的重载解析问题 [英] Overload resolution issue for generic method with constraints

查看:121
本文介绍了带约束的泛型方法的重载解析问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码示例:

 接口IFoo {} 
class FooImpl:IFoo {}

static void Bar< T>(IEnumerable< T> value)
其中T:IFoo
{
}

static void Bar< T>(T来源)
其中T:IFoo
{
}

Can有人解释,为什么这个方法调用:

  var value = new FooImpl [0]; 
Bar(value);

目标 Bar< T>(T source)(因此,不会编译)?

编译器在解析重载时是否考虑了类型参数约束?



UPD



避免与数组混淆。这发生在 IEnumerable< T> 的任何实现上,例如:

  var value = new List< FooImpl>(); 

UPD 2

@ ken2k提到了协方差。
但让我们忘掉 FooImpl 。这个:

  var value = new List< IFoo>(); 
Bar(value);

会产生相同的错误。

我相信, List< IFoo> IEnumerable< IFoo> 存在,因为我可以很容易地编写这样的内容:

  static void SomeMethod(IEnumerable< IFoo> sequence){} 

并将传递给它:

 的someMethod(值); 


解决方案


帐户类型参数约束在所有解决重载时?

不,因为通用约束不是函数签名的一部分。您可以通过添加一个 Bar 重载来验证这一点,该重载除了泛型约束外是完全相同的:

  interface IBar {} 

static void Bar< T>(IEnumerable< T> value)
其中T:IFoo
{
}

static void Bar< T>(T source)
其中T:IBar
{
//编译失败:类型____已经定义了一个名为'Bar'的成员,相同的参数类型
}

您的代码无法编译的原因是因为编译器选择基于方法签名的最佳匹配,然后尝试应用通用约束。



为什么它不是是因为这个调用是不明确的:



{假设 List< T> Add< T>(IEnumerable< T> source )方法}

 列表与LT;对象> junk = new List< object>(); 
junk.Add(1); // OK
junk.Add(xyzzy)// OK
junk.Add(new [] {1,2,3,4}); //不明确 - 您是否打算添加数组的_array_或_contents_?

显而易见的解决方法是为 Bar 使用集合的方法(就像BCL中的 Add AddRange


A code sample:

interface IFoo { }
class FooImpl : IFoo { }

static void Bar<T>(IEnumerable<T> value)
    where T : IFoo
{
}

static void Bar<T>(T source)
    where T : IFoo
{
}

Can anybody explain, why this method call:

var value = new FooImpl[0];
Bar(value);

targets Bar<T>(T source) (and, hence, doesn't compile)?

Does compiler take into account type parameter constraints at all, when resolving overloads?

UPD.

To avoid confusion with arrays. This happens with any implementation of IEnumerable<T>, e.g.:

var value = new List<FooImpl>();

UPD 2.

@ken2k mentioned covariance. But let's forget about FooImpl. This:

var value = new List<IFoo>();
Bar(value);

produces the same error.
I'm sure, that implicit conversion between List<IFoo> and IEnumerable<IFoo> exists, since I can easily write something like this:

static void SomeMethod(IEnumerable<IFoo> sequence) {}

and pass value into it:

SomeMethod(value);

解决方案

Does compiler take into account type parameter constraints at all, when resolving overloads?

No, because generic constraints are not part of the function signature. You can verify this by adding a Bar overload that is identical except for the generic constraints:

interface IBar { }

static void Bar<T>(IEnumerable<T> value)
    where T : IFoo
{
}

static void Bar<T>(T source)
    where T : IBar
{
    // fails to compile : Type ____ already defines a member called 'Bar' with the same parameter types
}

The reason your code doesn't compile is because the compiler chooses the "best" match based on the method signature, then tries to apply the generic constraints.

One possible reason why it doesn't is because this call would be ambiguous:

{suppose List<T> had an Add<T>(IEnumerable<T> source) method}

List<object> junk = new List<object>();
junk.Add(1);   // OK
junk.Add("xyzzy") // OK
junk.Add(new [] {1, 2, 3, 4});  //ambiguous - do you intend to add the _array_ or the _contents_ of the array?

The obvious fix is to use a different name for the Bar method that takes a collection (as is done in the BCL with Add and AddRange.

这篇关于带约束的泛型方法的重载解析问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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