这个让我感到沮丧,所以我想我会在这里问,希望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) { }
}
Run Code Online (Sandbox Code Playgroud)
有问题的错误:
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
Run Code Online (Sandbox Code Playgroud)
我使用的是什么类型并不重要 - 如果在该代码中用"int"替换"String"声明,您将得到相同类型的错误.这就像编译器不能告诉之间的区别Func<T>和Func<IEnumerable<T>>.
有人可以对此有所了解吗?
在以下代码中:
public class A
{
public decimal Decimal { get; set; }
}
public decimal Test()
{
return new List<A>().Sum(SumDecimal);
}
public decimal SumDecimal(A a)
{
return a.Decimal;
}
Run Code Online (Sandbox Code Playgroud)
该行return new List<A>().Sum(SumDecimal);有一个错误,指出这SumDecimal是一个模糊的调用.
为什么编译器无法推断出类型SumDecimal.但是,以下工作:
return new List<A>().Sum((Func<A, decimal>) SumDecimal);
Run Code Online (Sandbox Code Playgroud)
当然,通常的lambda方式也适用:
return new List<A>().Sum(x => SumDecimal(x));
Run Code Online (Sandbox Code Playgroud)
在更多实验中,如果我编写自己的扩展方法:
public static class MyExtensions
{
public static T MySum<T, T2>(this IEnumerable<T2> ie, Func<T2, T> d)
{
return default(T);
}
}
Run Code Online (Sandbox Code Playgroud)
并称之为,编译器推断得很好:
return new List<A>().MySum(SumDecimal);
Run Code Online (Sandbox Code Playgroud)
我看到,IEnumerable<T>.Sum目前超载int, …
我在IDataReader上有两个扩展方法,具有以下签名:
internal static List<T> GetList<T>(this IDataReader reader, Func<string, T> del)
internal static double? GetDoubleOrNull(this IDataReader reader, string columnName)
Run Code Online (Sandbox Code Playgroud)
GetDoubleOrNull 没有任何重载.
在其他地方,我能做到
Func<string, double?> del = reader.GetDoubleOrNull;
var x = reader.GetList(del);
Run Code Online (Sandbox Code Playgroud)
要么
var x = reader.GetList<double?>(reader.GetDoubleOrNull);
Run Code Online (Sandbox Code Playgroud)
或者只是传入一个类似的实例方法
public double? blah(string s)
var x = reader.GetList(blah);
Run Code Online (Sandbox Code Playgroud)
但我不能这样做
var x = reader.GetList(reader.GetDoubleOrNull);
Run Code Online (Sandbox Code Playgroud)
编译器给出错误
cannot convert from 'method group' to 'System.Func<string,double?>'
Run Code Online (Sandbox Code Playgroud)
我不明白这一点.我认为既然没有重载GetDoubleOrNull,就不会有重载决策,它可以从方法签名推断出类型参数.
真正令人困惑的部分是它在传入时的工作方式blah.
我正在玩一个非常简单的程序来获取一系列双打并返回标准偏差.这部分工作但我想让代码更可重用.我想这样做,所以该方法可以接受任何类型的参数,可以被认为是数字并返回标准偏差而不是硬编码双重类型(就像我最初在这个程序中做的那样).如何解决这个问题以及适当的术语是什么?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
double[] avg = { 3.4, 55.6, 10.0, 4.5, 2, 2 };
double x = avg.Average();
//first round of testing
Console.WriteLine("The average of the first array is below ");
Console.WriteLine(x);
Console.WriteLine("below should be the standard deviation!");
Console.WriteLine(CalculateStandardDeviation(avg));
Console.ReadLine();
int[] intAvg = { 4, 3, 5, 6, 2 };
double secondAvg = intAvg.Average();
Console.WriteLine("The average of the second array is below "); …Run Code Online (Sandbox Code Playgroud) 以下调用重载Enumerable.Select方法:
var itemOnlyOneTuples = "test".Select<char, Tuple<char>>(Tuple.Create);
Run Code Online (Sandbox Code Playgroud)
失败并出现歧义错误(为清晰起见,删除了名称空间):
The call is ambiguous between the following methods or properties:
'Enumerable.Select<char,Tuple<char>>
(IEnumerable<char>,Func<char,Tuple<char>>)'
and
'Enumerable.Select<char,Tuple<char>>
(IEnumerable<char>, Func<char,int,Tuple<char>>)'
Run Code Online (Sandbox Code Playgroud)
我当然可以理解为什么不明确指定类型参数会导致歧义(两个都会应用重载),但是在这样做后我没有看到.
对我来说似乎很清楚,目的是调用第一个重载,方法组参数解析为Tuple.Create<char>(char).第二个重载不应该适用,因为没有任何 Tuple.Create重载可以转换为期望的Func<char,int,Tuple<char>>类型.我猜测编译器很困惑Tuple.Create<char, int>(char, int),但它的返回类型是错误的:它返回一个二元组,因此不能转换为相关Func类型.
顺便说一句,以下任何一个使编译器开心:
Tuple.Create<char>也许这实际上是一个类型推断问题?).x => Tuple.Create(x).(在Select通话中使用类型推断很好).不出所料,尝试以Select这种方式调用其他重载也会失败:
var itemIndexTwoTuples = "test".Select<char, Tuple<char, int>>(Tuple.Create);
Run Code Online (Sandbox Code Playgroud)
这里的确切问题是什么?