我对 C# 如何处理隐式转换的 lambda 表达式有点困惑。
我的目标类似于以下最小示例:
A<int>.DoSomething(x => x == 42);
public static class A<T>
{
public static void DoSomething(PredicateAdapter<T> _) { }
}
public class PredicateAdapter<T>
{
public static implicit operator PredicateAdapter<T>(Predicate<T> _) => new();
}
所以我想为谓词创建一个包装器,它允许我做一些奇特的事情(为了简洁起见,在本示例中没有列出。)但是,上面的代码无法编译,因为“Error CS1660:无法将 lambda 表达式转换为类型“PredicateAdapter”,因为它不是委托类型”。
相反,下面是隐式转换起作用的示例:
A<int>.DoSomething(x => x == 42);
public static class A<T>
{
public static void DoSomething(Predicate<T> _) { }
}
编译器能够推断 lambda 表达式
x => x == 42
可以隐式转换为 Predicate<int>
并将其愉快地传递给 A<int>.DoSomething(Predicate<int>)
。
此外,将 lambda 显式转换为
Predicate<int>
意味着我的自定义隐式转换已应用并且有效:
A<int>.DoSomething((Predicate<int>)(x => x == 42));
public static class A<T>
{
public static void DoSomething(PredicateAdapter<T> _) { }
}
public class PredicateAdapter<T>
{
public static implicit operator PredicateAdapter<T>(Predicate<T> _) => new();
}
所以,我的问题是:当 C# 显然能够隐式执行此转换时,为什么我需要显式转换 lambda(并编写可读性低得多的代码)?并且:是否可以以某种方式修改类
A
和 PredicateAdapter
,以便我可以使用简单的 lambda 表达式(无需任何显式转换)并仍然使用 PredicateAdapter
?
根据我的理解,这是“因为规范是这么说的”。正如 12.19 匿名函数表达式 部分所述:
匿名函数本身没有值或类型,但可以转换为兼容的委托或表达式树类型。
因此,当您使用匿名函数(lambda 表达式)时,编译应该决定它应该是什么类型(因为您没有显式指定类型)。因为您的参数不是委托类型(如
Predicate<T>
)或表达式树类型(即 Expression<Func<T, TResult>>
)。
同样来自 10.7 匿名函数转换:
或anonymous_method_expression
被归类为匿名函数(第 12.19 节)。该表达式没有类型,但可以隐式转换为兼容的委托类型。某些 lambda 表达式也可以隐式转换为兼容的表达式树类型。lambda_expression
C# 10 中的 Lambda 改进 也很有趣。