取两个可以为空的值
假设我有两个可以为空的整数:
int? a = 10; int? b = 20;
我想取最大的非null值,这样如果两个值都为null,则结果为null。
我可以写一些啰嗦的东西,例如:
int? max; if (a == null) { max = b; } else if (b == null) { max = a; } else { max = a > b ? a : b; }
对于我的喜好,这感觉有点过于笨重(并且可能容易出错)。 返回更大值的最简单方法是什么,这也是空值的可能性?
这适用于任何可以为空的:
Nullable.Compare(a, b) > 0? a: b;
在一行中使用null合并运算符:
int? c = a > b ? a : b ?? a;
这些行显示了一个小技巧的必要逻辑:
if (a == null) return b; // handles b== null also if (b == null) return a; // now a!=null, b!=null return Math.Max(a.Value, b.Value);
或者在一行中使用?:
完全相同的逻辑)
return a == null ? b : b == null ? a : Math.Max(a.Value, b.Value);
编辑
虽然上述答案对于教育目的而言很有意思,但并不是解决这个问题的推荐方法。 推荐的方法是不重新发明轮子而是找到匹配的轮子:
正如@roman指出的那样,存在一个Nullable.Compare()
方法,这使得它更具可读性:
return Nullable.Compare(a, b) > 0 ? a : b;
这是Null合并算子的好地方??
。
如果值不为null
,则返回第一个值,否则返回第二个值。
int? c = a > b ? a : b ?? a;
certificate在这里
如果任一值为null
,则使用比较运算符将返回false
的事实,表达式将为您提供所需的结果:
a | b || a>b | a | b??a | a>b ? a : b??a --------------------||---------------------------------- > b | NOT NULL || T | a | -- | a ≤ b | NOT NULL || F | -- | b | b NOT NULL | NULL || F | -- | a | a NULL | NOT NULL || F | -- | b | b NULL | NULL || F | -- | NULL | NULL
简短版本是:
var result = new[] { a, b }.Max();
这个怎么样
private int? Greater(int? a, int? b) { if(a.HasValue && b.HasValue) return a > b ? a : b; if(a.HasValue) return a; if(b.HasValue) return b; return null; }
或者更简洁:
private int? Greater(int? a, int? b) { if(a.HasValue && b.HasValue) return a > b ? a : b; return a.HasValue ? a : b; }
!b.HasValue || a > b ? a : b
如果b
为null( !b.HasValue
),则a
始终是正确的答案。
如果b
不为null但是a
,则a > b
将为false, b
将是正确答案。
否则它是相同的a > b ? a : b
a > b ? a : b
不可为空的整数会有。
如何制作一个能够处理尽可能多的可空值的方法:
public static int? GetLargestNonNull(params int?[] values) { IEnumerable nonNullValues = values.Where(v => v.HasValue); if (nonNullValues.Any()) { return nonNullValues.Select(v => v.Value).Max(); } return null; }
并使用如下:
int? result = GetLargestNonNull(a, b);
除此之外还能够处理:
int? result = GetLargestNonNull(a, b, c, d, e, f);
或者,如果您正在使用从其他来源收到的值,则可以更改方法参数以接受列表。
我想补充一点,这里的单线解决方案很好。 但是为了揭开代码的神秘面纱 ,在null合并运算符周围添加一个括号
private int? Max(int? a, int? b) { return a > b ? a : (b ?? a); //returns a if bigger else non null prefering b }
如果它更大则返回b ?? a
,否则返回b ?? a
b ?? a
– 返回非null(如果两者都为null,则返回null)更喜欢b
这是一个非常直观和可读的解决方案。 这适用于任何数量的值以及任何可以为null的结构,例如say,int? 还是日期时间?
此外,如果所有值都为null,则返回null。
public static T? GetGreatestOrDefault(IEnumerable values) where T : struct { var any = values.Any(a => a.HasValue); if (!any) return null; var firstOrDefault = values.Where(v => v.HasValue) .Select(v => v.Value) .OrderByDescending(o => o) .FirstOrDefault(); return firstOrDefault; }
或者您可能想要执行以下操作:
public static T? GreatestOrDefault(this IEnumerable values) where T : struct { var any = values.Any(a => a.HasValue); if (!any) return null; var firstOrDefault = values.Where(v => v.HasValue).Max(); return firstOrDefault; }