【发布时间】:2015-07-28 02:57:21
【问题描述】:
以下函数对尝试复制 C# 6.0 中可用的空条件运算符:
public static TResult Bind<T, TResult>(this T obj, Func<T, TResult> func)
where T : class
{
return obj == null ? default(TResult) : func(obj);
}
public static TResult Bind<T, TResult>(this Nullable<T> obj, Func<T, TResult> func)
where T : struct
{
return obj.HasValue ? func(obj.Value) : default(TResult);
}
第一个函数仅限于类,对于 String s,我可以编写如下内容:
var x = s.Bind(a => a.Substring(1));
第二个功能是我遇到麻烦的地方。例如,给定一个int? number 我想写:
var y = number.Bind(a => a + 1);
但是,这给了我以下错误:
以下方法或属性之间的调用不明确:'BindingExtensions.Bind
(T, Func )' 和 'BindingExtensions.Bind (T?, Func)'
我猜这与匿名函数的类型推断和方法重载解析之间的相互作用有关。如果我将 a 的类型指定为 int ,则它编译得很好。
var y = number.Bind((int a) => a + 1);
但是,这显然不太理想。谁能告诉我为什么编译器认为上述绑定调用是模棱两可的和/或提供解决此问题的方法?我知道我可以简单地将这两个函数命名为不同的名称,但这有什么好玩的呢?
【问题讨论】:
-
您可以删除第一个约束,而不再需要第二个约束。当然,对于
null值,number.Bind(a=>a+1)的结果将是null而不是 0。但这就是我所期望的结果。 -
@juharr 但这会破坏目的。我希望匿名函数的输入永远不会为空,这就是为什么第二个函数在 Nullable
上运行但只将 T 传递给匿名函数的原因。 -
你的函数不会被传递一个
null,因为obj == null对于Nullable<T>来说是真的,而HasValue是假的。当然,这意味着您的函数必须期待Nullable<int>而不是int,但这就是我所期望的。 -
@juharr 我不同意,我希望
int而不是int?正是因为它永远不能为空。我对此的灵感来自于 monads 的功能思想(这就是我将函数命名为Bind的原因)。我认为Bind可以将变量从其可为空的上下文中取出并对其进行操作。
标签: c#