Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.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# 为什么Func<;T>;与Func不明确<;IEnumerable<;T>>;?_C#_Generics - Fatal编程技术网

C# 为什么Func<;T>;与Func不明确<;IEnumerable<;T>>;?

C# 为什么Func<;T>;与Func不明确<;IEnumerable<;T>>;?,c#,generics,C#,Generics,这件事让我很困惑,所以我想我应该在这里问一下,希望C#guru能向我解释一下 为什么这段代码会产生错误 class Program { static void Main(string[] args) { Foo(X); // the error is on this line } static String X() { return "Test"; } static void Foo(Func<IEnumerable<Str

这件事让我很困惑,所以我想我应该在这里问一下,希望C#guru能向我解释一下

为什么这段代码会产生错误

class Program
{
    static void Main(string[] args)
    {
        Foo(X); // the error is on this line
    }

    static String X() { return "Test"; }

    static void Foo(Func<IEnumerable<String>> x) { }
    static void Foo(Func<String> x) { }
}
类程序
{
静态void Main(字符串[]参数)
{
Foo(X);//错误在这一行
}
静态字符串X(){return“Test”;}
静态void Foo(Func x){}
静态void Foo(Func x){}
}
有关错误:

Error
    1
    The call is ambiguous between the following methods or properties:
'ConsoleApplication1.Program.Foo(System.Func<System.Collections.Generic.IEnumerable<string>>)' and 'ConsoleApplication1.Program.Foo(System.Func<string>)'
    C:\Users\mabster\AppData\Local\Temporary Projects\ConsoleApplication1\Program.cs
    12
    13
    ConsoleApplication1
错误
1.
以下方法或属性之间的调用不明确:
“ConsoleApplication1.Program.Foo(System.Func)”和“ConsoleApplication1.Program.Foo(System.Func)”
C:\Users\mabster\AppData\Local\Temporary Projects\ConsoleApplication1\Program.cs
12
13
控制台应用程序1
我使用什么类型并不重要——如果在代码中用“int”替换“String”声明,您将得到相同类型的错误。就像编译器无法区分
Func
Func
之间的区别一样

有人能解释一下吗?

您的代码需要“魔法”发生两次,一次是从命名方法组转换为委托,一次是执行重载解析

尽管您只有一个名为
X
的方法,但编译器规则是针对存在多个方法的情况构建的

此外,由于委托不必精确匹配方法签名,因此复杂性进一步增加。除此之外,任何给定的方法都可以转换为具有相同签名的无限数量的不同委托类型

您的特殊情况看起来很简单,但一般情况非常困难,因此语言不允许这样做

如果你用手做部分工作,你就能解决问题。e、 g

Func<string> d = X;
Foo(d);
Func d=X;
傅(丁),;
应该可以编译。

好的,就这么定了

简短版本:

  • 奇怪的是,歧义错误是正确的
  • C#4编译器在正确的歧义错误之后还会产生一个伪错误。这似乎是编译器中的一个bug
长版本:

我们有一个过载解决问题。重载分辨率非常明确

第一步:确定候选集。那很容易。候选人是
Foo(Func)
Foo(Func)

第二步:确定候选集的哪些成员适用。适用成员的每个参数都可转换为每个参数类型


Foo(Func)
是否适用?那么,
X
是否可转换为
Func“如果返回类型不匹配,那么最好说没有方法组来委托转换”:对我来说似乎确实更好。。。我不认为改变这个规则会是一个破坏性的改变,是吗?我的意思是,据我所知,没有办法生成使用这种转换的工作代码(也许我没有足够努力,但我总是得到“XXX有错误的返回类型”)@Thomas:将过去的错误转化为成功案例可以将过载解决问题从一个解决方案转化为两个不明确的解决方案,这将使成功案例转化为错误案例!令人惊讶的是,有多少事情在技术上是突破性的变化,但在这种情况下,我认为这可能是值得的。我将与Mads讨论它。引用:“重载解析总是忽略返回类型”和“lambda和方法组有不同的可兑换规则”——非常不幸,但我认为这是一个很好的解释!