问题
考虑以下两个扩展方法,它们只是从任何类型 T1
映射到 T2
的简单映射,再加上一个重载以流畅地映射 Task<T>
:
public static class Ext {
public static T2 Map<T1, T2>(this T1 x, Func<T1, T2> f)
=> f(x);
public static async Task<T2> Map<T1, T2>(this Task<T1> x, Func<T1, T2> f)
=> (await x).Map(f);
}
现在,当我使用第二个重载并映射到引用类型时...
var a = Task
.FromResult("foo")
.Map(x => $"hello {x}"); // ERROR
var b = Task
.FromResult(1)
.Map(x => x.ToString()); // ERROR
我遇到了以下错误:
CS0121:调用以下方法或属性时存在歧义:“Ext.Map(T1, Func)”和“Ext.Map(Task, Func)”
将值类型映射正常工作:
var c = Task
.FromResult(1)
.Map(x => x + 1); // works
var d = Task
.FromResult("foo")
.Map(x => x.Length); // works
但是仅当映射实际使用输入生成输出时:
var e = Task
.FromResult(1)
.Map(_ => 0); // ERROR
问题
有没有人能够解释一下这里到底发生了什么?我已经放弃寻找可行的解决方案来修复此错误,但至少我想了解这一混乱的根本原因。
额外说明
到目前为止,我发现了三种解决方法,但在 我的用例 中都不可行。第一种是显式指定 Task<T1>.Map<T1,T2>()
的类型参数:
var f = Task
.FromResult("foo")
.Map<string, string>(x => $"hello {x}"); // works
var g = Task
.FromResult(1)
.Map<int, int>(_ => 0); // works
另一种解决方法是不使用 lambda:
string foo(string x) => $"hello {x}";
var h = Task
.FromResult("foo")
.Map(foo); // works
第三个选项是将映射限制为端函数(即Func<T,T>
):
public static class Ext2 {
public static T Map2<T>(this T x, Func<T, T> f)
=> f(x);
public static async Task<T> Map2<T>(this Task<T> x, Func<T, T> f)
=> (await x).Map2(f);
}
我 创建了一个.NET Fiddle,您可以在其中尝试上述示例。