我试图在c#中编写一个一般的单一性模式,从一个结合两个非空值的齐次函数开始,如果另一个为空,则返回值,或者如果两者都不是,则返回组合值,或为空。这里是:
public static Func<TIn?, TIn?,TIn?> Drop2<TIn>(Func<TIn, TIn, TIn> f)
{
return (lhs, rhs) =>
{
if (lhs == null && rhs == null)
{
return default;
}
if (lhs == null && rhs != null)
{
return rhs;
}
if (rhs == null && lhs != null)
{
return lhs;
}
return f(lhs, rhs);
};
}
这看起来很好,甚至可以编译,但是当我尝试使用它时,发生了两件奇怪的事情。
Func<int, int, int> sum = (lhs, rhs) => lhs + rhs;
var sumNonNull = DropNullable.Drop2(sum);
sumNonNull的智能感知显示为Func<int, int, int>?
,而不是预期的Func<int?, int?, int?>
,并且我不能将null作为sumNonNull的参数传递(不能从int转换?int)。
这应该工作吗?我错过了什么?
提前感谢您的帮助
我想你需要这样的东西:
public static Func<TIn?, TIn?, TIn?> Drop2<TIn>(Func<TIn?, TIn?, TIn?> f)
{
return (lhs, rhs) =>
lhs is null ? rhs
: rhs is null ? lhs
: f(lhs, rhs);
}
注意输入参数中的TIn?
和结果(它们都可以是null
)。然后你可以这样使用:
// note int? - sumInt accepts nulls (int? is a short for Nullable<int>)
Func<int?, int?, int?> sumInt = (a, b) => a + b;
Console.WriteLine(Drop2(sumInt)(null, 123));
Console.WriteLine(Drop2(sumInt)(456, null));
Console.WriteLine(Drop2(sumInt)(456, 123));
Console.WriteLine(Drop2(sumInt)(null, null));
// strings can be null
Func<string, string, string> sumStr = (a, b) => a + b;
Console.WriteLine(Drop2(sumStr)(null, "123"));
Console.WriteLine(Drop2(sumStr)("456", null));
Console.WriteLine(Drop2(sumStr)("456", "123"));
Console.WriteLine(Drop2(sumStr)(null, null));