Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#泛型重载-编译器可以';无法确定正确的呼叫_C#_Generics_Overloading - Fatal编程技术网

C#泛型重载-编译器可以';无法确定正确的呼叫

C#泛型重载-编译器可以';无法确定正确的呼叫,c#,generics,overloading,C#,Generics,Overloading,我不明白为什么编译器不能解析这里要使用的正确重载。(下面的代码)只有一个版本的Add()是合适的-BigFoo是一个IFoo,不实现IEnumerable,其中T是一个IFoo。但它坚持报告一个模棱两可的问题。有什么想法吗?我尝试添加第二个泛型类型参数-addwhere T:IFoo where U:IEnumerable。但是,即使是合法使用,过载也会被完全忽略 我知道我可以通过强制转换和指定泛型类型参数来解决这个问题,但在这一点上,我已经挫败了重载的目的。您可以对重载提出疑问,但我觉得语义是

我不明白为什么编译器不能解析这里要使用的正确重载。(下面的代码)只有一个版本的Add()是合适的-BigFoo是一个IFoo,不实现IEnumerable,其中T是一个IFoo。但它坚持报告一个模棱两可的问题。有什么想法吗?我尝试添加第二个泛型类型参数-addwhere T:IFoo where U:IEnumerable。但是,即使是合法使用,过载也会被完全忽略

我知道我可以通过强制转换和指定泛型类型参数来解决这个问题,但在这一点上,我已经挫败了重载的目的。您可以对重载提出疑问,但我觉得语义是正确的-我在类中实现的行为是Add()将对象作为集合中的单个条目整体添加。(第二个Add()不应该是AddRange()

NS
{
接口IFoo{}
类BigFoo:IFoo,IEnumerable
{
公共IEnumerator GetEnumerator()
{
抛出新的NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
抛出新的NotImplementedException();
}
}
类FooContainer
{
公共无效添加(IFoo项){}
公共void Add(IEnumerable组),其中T:IFoo{}
}
类DemoClass
{
void DemoMethod()
{
BigFoo BigFoo=新的BigFoo();
FooContainer=新的FooContainer();
//错误CS0121:以下方法或属性之间的调用不明确:
//'NS.FooContainer.Add(NS.IFoo)'和
//'NS.FooContainer.Add(System.Collections.Generic.IEnumerable)'
fooContainer.Add(bigFoo);
}
}
}

通用重载解析不考虑约束,因此它认为
Add
版本适用,从而推断
t=int


这两种方法都适用,而且两者都不一定比另一种好,因为
IEnumerable
IFoo
之间没有转换。虽然泛型方法被视为比非泛型方法“不太具体”,但这只有在类型参数替换后参数类型相同时才有意义,而在这种情况下,参数类型不同。

编译器应该足够聪明,能够认识到
BigFoo
不能强制转换为
IEnumerable
,但事实并非如此。它只是看到它是一个
IEnumerable
,并且感觉它是一个潜在的重载候选对象(即使您定义的contstraint强制执行
T
必须是
IFoo
,并且
int
不能转换为
IFoo
)。虽然不方便,但也没什么大不了的。只要将bigFoo转换为
IFoo
,编译器就会很高兴:

fooContainer.Add((IFoo)bigFoo);
或者,您可以使添加的通用重载更加丑陋:

public void Add<T, U>(U group)
    where T : IFoo
    where U : IEnumerable<T>
{
}

在FooContainer中,在第二个“Add”中,您将T约束为IFoo类型。BigFoo实现了IFoo接口,因此它有点匹配添加的定义(尽管它实际上没有,因为它没有实现IEnumable)

我不确定我完全理解你想要什么,但我怀疑是这样的:

public void Add<T>(T group) where T : IEnumerable<IFoo> { }
public void Add(T组),其中T:IEnumerable{}
这将允许您添加任何对象T,其中T是IFoo对象的可枚举集

这就是你想要的吗

问候,,
Richard这里的问题是编译器完全忽略了泛型类型约束(它只查看参数类型)。就编译器而言,传递的
IEnumerable
参数也可以是
IEnumerable


有关此主题的完整信息,请参阅第25.6.4节的类型参数推断。请注意,没有提到类型约束的使用。

有趣。。。。刚刚试过你的样品。仿制药继续让我保持警觉

//1 - First preference
public void Add(BigFoo item) { Console.WriteLine("static BigFoo type Add"); }
//2 - Second Preference
public void Add<T>(T item) { Console.WriteLine("Generic Add");  }
//3 - Third preferences
public void Add(IFoo item) { Console.WriteLine("static IFoo interface Add"); }
//4 - Compiles if 1-4 exist. Compile error (ambiguity) if only 3-4 exist. Compile error (cannot convert int to IFoo) if only 4 exists
public void Add<T>(IEnumerable<T> group) where T : IFoo { }
//1-首选项
公共void添加(BigFoo项){Console.WriteLine(“静态BigFoo类型添加”);}
//2秒优先
public void Add(T项){Console.WriteLine(“Generic Add”);}
//3-第三选择
公共void添加(IFoo项){Console.WriteLine(“静态IFoo接口添加”);}
//4-如果存在1-4,则编译。如果仅存在3-4,则编译错误(歧义)。如果仅存在4,则编译错误(无法将int转换为IFoo)
公共void Add(IEnumerable组),其中T:IFoo{}

不过,将T约束为IEnumerable而不是IFoo仍然无助于重载解析。正如Jon Skeet所说,编译器(不幸地)不会考虑约束。啊。。。酷。今天学到了新东西。:-)谢谢你抽出时间来评论——我真的认为编译器会考虑“WHE”子句中的约束,即使在方法签名的别处没有考虑到它们。Jeff Richter同意“C编译器比通用匹配更喜欢显式匹配”显示(“杰夫”)将匹配显示(字符串)显示(t)。仅当形式参数类型相同时,才适用平局打破规则。例如,如果你有M(intx)和M(tt),那么前者比M(intt)好。啊,谢谢Eric。将规范联机并提供帮助是很好的;)将进行适当编辑。这不是寻找与此问题密切相关的规范规则的相关位置。3.0规范中的相关章节为7.5.5.1,即开始“对所选最佳方法进行最终验证”的bit。从本节可以看到,约束冲突检查是在检查候选集的唯一性之后执行的。啊,对了。当然,规范的这一部分至少表明在推理过程中没有考虑泛型类型约束,然而?事实上,在推理过程中也没有使用约束。
public void Add<T>(T group) where T : IEnumerable<IFoo> { }
//1 - First preference
public void Add(BigFoo item) { Console.WriteLine("static BigFoo type Add"); }
//2 - Second Preference
public void Add<T>(T item) { Console.WriteLine("Generic Add");  }
//3 - Third preferences
public void Add(IFoo item) { Console.WriteLine("static IFoo interface Add"); }
//4 - Compiles if 1-4 exist. Compile error (ambiguity) if only 3-4 exist. Compile error (cannot convert int to IFoo) if only 4 exists
public void Add<T>(IEnumerable<T> group) where T : IFoo { }