取两个可为空的值中的较大者
Take the greater of two nullable values
假设我有两个可为空的整数:
int? a = 10;
int? b = 20;
我想取最大的非空值,如果两个值都为空,则结果为空。
我可以写一些冗长的东西,比如:
int? max;
if (a == null)
{
max = b;
}
else if (b == null)
{
max = a;
}
else
{
max = a > b ? a : b;
}
我觉得这有点太笨重(而且可能容易出错)。 return 更大值的最简单方法是什么,这也说明了空值的可能性?
这些行通过一个小技巧显示了必要的逻辑:
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;
这个怎么样
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;
}
在使用空合并运算符的一行中:
int? c = a > b ? a : b ?? a;
一个简短的版本是:
var result = new[] { a, b }.Max();
!b.HasValue || a > b ? a : b
如果 b
为空 (!b.HasValue
),则 a
始终是正确答案。
如果 b
不为空而 a
为空,则 a > b
为假,b
为正确答案。
否则它与不可为 null 的整数所具有的 a > b ? a : b
相同。
如何制作一个能够处理尽可能多的可为空值的方法:
public static int? GetLargestNonNull(params int?[] values)
{
IEnumerable<int?> 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 coalescing operator??
的好地方。
如果值不是 null
,它 return 是第一个值,否则它 return 是第二个值。
int? c = a > b ? a : b ?? a;
使用比较运算符将 return false
如果任一值是 null
,表达式将给出所需的结果:
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
这适用于任何可空值:
Nullable.Compare(a, b) > 0 ? a : b;
我想补充一点,这里的 one-line 解决方案很好。但是为了 demystify 代码在 null coalescing operator
周围添加一个 brackets
private int? Max(int? a, int? b)
{
return a > b ? a : (b ?? a);
//returns a if bigger else non null prefering b
}
Returns a
如果它更大,否则 return b ?? a
- returns 非空(如果都为空则为空)更喜欢 b
这是一个非常直观易读的解决方案。这将适用于任意数量的值以及任何可为空的结构,例如 int?或日期时间?
此外,如果所有值都为空,则它 returns 为空。
public static T? GetGreatestOrDefault<T>(IEnumerable<T?> 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<T>(this IEnumerable<T?> 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;
}
假设我有两个可为空的整数:
int? a = 10;
int? b = 20;
我想取最大的非空值,如果两个值都为空,则结果为空。
我可以写一些冗长的东西,比如:
int? max;
if (a == null)
{
max = b;
}
else if (b == null)
{
max = a;
}
else
{
max = a > b ? a : b;
}
我觉得这有点太笨重(而且可能容易出错)。 return 更大值的最简单方法是什么,这也说明了空值的可能性?
这些行通过一个小技巧显示了必要的逻辑:
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;
这个怎么样
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;
}
在使用空合并运算符的一行中:
int? c = a > b ? a : b ?? a;
一个简短的版本是:
var result = new[] { a, b }.Max();
!b.HasValue || a > b ? a : b
如果 b
为空 (!b.HasValue
),则 a
始终是正确答案。
如果 b
不为空而 a
为空,则 a > b
为假,b
为正确答案。
否则它与不可为 null 的整数所具有的 a > b ? a : b
相同。
如何制作一个能够处理尽可能多的可为空值的方法:
public static int? GetLargestNonNull(params int?[] values)
{
IEnumerable<int?> 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 coalescing operator??
的好地方。
如果值不是 null
,它 return 是第一个值,否则它 return 是第二个值。
int? c = a > b ? a : b ?? a;
使用比较运算符将 return false
如果任一值是 null
,表达式将给出所需的结果:
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
这适用于任何可空值:
Nullable.Compare(a, b) > 0 ? a : b;
我想补充一点,这里的 one-line 解决方案很好。但是为了 demystify 代码在 null coalescing operator
周围添加一个 bracketsprivate int? Max(int? a, int? b)
{
return a > b ? a : (b ?? a);
//returns a if bigger else non null prefering b
}
Returns a
如果它更大,否则 return b ?? a
- returns 非空(如果都为空则为空)更喜欢 b
这是一个非常直观易读的解决方案。这将适用于任意数量的值以及任何可为空的结构,例如 int?或日期时间?
此外,如果所有值都为空,则它 returns 为空。
public static T? GetGreatestOrDefault<T>(IEnumerable<T?> 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<T>(this IEnumerable<T?> 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;
}