a ?? b
a
不是null
=>返回a
。a
是null
)=>返回b
。我想模拟它的反转(AFAIK没有操作符来执行此操作):
a
是null
=>返回a
。a
不是null
)=>返回b
。我们的想法是b
是接收a
并需要避免null
参数的函数的结果。像这样:a XX fn(a)
其中XX将是运算符(如果存在)。
我唯一的两个变种是:
a == null ? a : fn(a)
a == null ? null : fn(a)
有没有办法简化这段代码?
答案 0 :(得分:3)
不确定您要完成的是什么?像这样的东西?
TResult NullFn<TParam, TResult>(TParam a, Func<TParam, TResult> method)
{
if(a == null) return null;
return method(a);
}
...
var result = NullFn(a, a => fn(a))
但是,如果传递空值,那么恕我直言的最佳解决方案就是让fn
返回null。
编辑:
顶部的方法只是一个例子。您可能希望在某个特定区域中一次又一次地执行大量相同操作的情况下使用此类内容,并且您无法更改fn,因为这样可以更容易地关注其余部分代码,您可能希望将来一次性改变所有操作的空值处理行为。 (我假设情况就是这样,因为你首先要问的。)但我不会在整个应用程序中使用它,因为如果你没有{{1}我不清楚发生了什么功能就在你面前。
答案 1 :(得分:1)
简单条件有什么不对?
if (a != null) b = fn(a);
另一个选项 - 为方法添加条件:
public B fn(A a)
{
if (a == null)
return null;
return new B();
}
答案 2 :(得分:1)
我个人更喜欢
(a != null) ? fn(a) : null
因为我认为它使意图更加明显,但我想不出一种简化那么多的方法。如果您愿意,可以使用扩展方法。
a.CallIfNotNull(fn)
使用以下扩展方法
internal static T CallIfNotNull<T>(this T value, Func<T, T> function)
where T : class
{
return (value != null) ? function(value) : null;
}
不是更好,但可能更不容易出错,并且在给定的IntelliSense时更容易输入。
(假设函数返回与问题所暗示的参数类型相同的值。)
答案 3 :(得分:0)
如果T a;
和T fn(T a);
使用相同的用户定义类型T,那么您可以编写a && fn(a)
并将其扩展为T.False(a) ? a : T.&(a, fn(a))
。
答案 4 :(得分:0)
您已经使用底部的?:实现回答了自己的问题。
我建议的唯一改进是将功能包装在一个方法中,使其更清晰,更不容易出错。
object SafeB(object a)
{
return a==null ? a : b(a);
}
编译器可能会内联这个,这样你就不会失去性能。
您甚至可以将其实现为提供b的类的扩展方法,以使其成为更加集成的解决方案。