C# 中奇妙的函数–5. Nullable 静态类
2011-08-25 08:40
302 查看
前段时间忙于各处奔波没有写博,今天想和大家再来看看一个奇妙的函数。
首先假设你不得不处理一些已有的代码,里面用到了nullable(可空值类型)的变量, 你必须要用这变量与不可空变量比较.
[/code]
有人可能认为要么结果为“是”, 要么 抛出 NullReferenceException, 对吗? 因为一个null的整型在我们理解中是比100小,但是运行的结果为“否”!
下面的例子更加的令人费解,因为结果也为“否”:
[/code]
那么,我们说 null 小于所有的有效整型, 对吗? 如果对的话,你怎么看这段代码:
[/code]
如果我们使用大于符号判断时:
[/code]
结果使用四种比较运算符 ( <, >, <=, >= ) 全都返回否。 这个同样适用于其他有这样运算符定义的类型: short, float, double, DateTime, TimeSpan。
在.net 机制下 null 不是一个大数值,也不是小数值,比较时也不会发生异常。
更奇怪的事:
[/code]
再看看下面的代码:
[/code]
。。
但是,如果我们把null 看成是一个非常低的值应该怎么办?
例如,如果我们要排序一个列表。在列表中显示的是公司当前的股票价格:
代号 描述 价位
------ ----------------------- ----------
ABCZ Apples and Oranges Inc n/a
XYZP Zippers and Buttons Inc 1.57
AZAZ Carrots and Turnips Inc 23.13
比较运算符不适用于 null,因此,我们不得不做一些非常复杂的逻辑,如:
[/code]
我们也许可以简化这个函数,但它仍然是相当凌乱!但有一个更清洁的方式做到这一点,
如果你在MSDN上 读到 IComparer如何工作:
当使用 IComparable 时,允许将 Nothing 与任何类型进行比较,而且不会生成异常。 排序时,Nothing 被视为小于任何其他对象。
所以,我们可以改变我们的逻辑使用Nullable.Compare <T>( )静态方法 :
[/code]
C#/.NET Little Wonders: The Nullable static class
首先假设你不得不处理一些已有的代码,里面用到了nullable(可空值类型)的变量, 你必须要用这变量与不可空变量比较.
使用 <, >, <=, >= 来比较 nullable 值
看下面的代码:[code]1: int? x = null;
2:
3: if (x < 100)
4: {
5: Console.WriteLine("是, {0} 小于 100.",
6: x.HasValue ? x.ToString() : "null");
7: }
8: else
9: {
0: Console.WriteLine("否, {0} 不小于 100.",
1: x.HasValue ? x.ToString() : "null");
2: }
[/code]
有人可能认为要么结果为“是”, 要么 抛出 NullReferenceException, 对吗? 因为一个null的整型在我们理解中是比100小,但是运行的结果为“否”!
下面的例子更加的令人费解,因为结果也为“否”:
[code]1: int? x = null;
2:
3: if (x < int.MaxValue)
4: {
5: // ...
6: }
[/code]
那么,我们说 null 小于所有的有效整型, 对吗? 如果对的话,你怎么看这段代码:
[code]1: int? x = null;
2:
3: // 等等,X 不小于MinValue?
4: if (x < int.MinValue)
5: {
6: //...
7: }
[/code]
如果我们使用大于符号判断时:
[code]1: int? x = null;
2:
3: // x 也不大于MinValue….
4: if (x > int.MinValue)
5: {
6: //...
7: }
[/code]
结果使用四种比较运算符 ( <, >, <=, >= ) 全都返回否。 这个同样适用于其他有这样运算符定义的类型: short, float, double, DateTime, TimeSpan。
在.net 机制下 null 不是一个大数值,也不是小数值,比较时也不会发生异常。
更奇怪的事:
[code]1: DateTime? x = null;
2: DateTime? y = null;
3:
4: if (x <= y)
5: {
6: Console.WriteLine("你觉得他们相等吗?");
7: }
8: else
9: {
10: Console.WriteLine("结果不是:<=, <, >, >= 根本不适用于null.");
11: }
[/code]
再看看下面的代码:
[code]1: int? x = null;
2: int? y = 100;
3:
4: if (x < y)
5: {
6: Console.WriteLine("X 小于 Y");
7: }
8: else if (x > y)
9: {
10: Console.WriteLine("X 大于 Y");
11: }
12: else
13: {
14: // 这个才是我们得到的结果
15: Console.WriteLine("X 等于 Y");
16: }
[/code]
。。
解决方案: nullable 静态类
因此,我们已经看到,<,<=,>,和>= 有一些有趣的意外行为。但是,如果我们把null 看成是一个非常低的值应该怎么办?
例如,如果我们要排序一个列表。在列表中显示的是公司当前的股票价格:
代号 描述 价位
------ ----------------------- ----------
ABCZ Apples and Oranges Inc n/a
XYZP Zippers and Buttons Inc 1.57
AZAZ Carrots and Turnips Inc 23.13
比较运算符不适用于 null,因此,我们不得不做一些非常复杂的逻辑,如:
[code]1: if (x.HasValue)
2: {
3: if (y.HasValue)
4: {
5: if (x < y)
6: {
7: Console.WriteLine("x < y");
8: }
9: else if (x > y)
0: {
1: Console.WriteLine("x > y");
2: }
3: else
4: {
5: Console.WriteLine("x == y");
6: }
7: }
8: else
9: {
0: Console.WriteLine("x > y 因为 y 是 null, x 不是");
1: }
2: }
3: else if (y.HasValue)
4: {
5: Console.WriteLine("x < y 因为 x 是 null, y 不是");
6: }
7: else
8: {
9: Console.WriteLine("x == y 因为 都为 null");
0: }
[/code]
我们也许可以简化这个函数,但它仍然是相当凌乱!但有一个更清洁的方式做到这一点,
如果你在MSDN上 读到 IComparer如何工作:
当使用 IComparable 时,允许将 Nothing 与任何类型进行比较,而且不会生成异常。 排序时,Nothing 被视为小于任何其他对象。
所以,我们可以改变我们的逻辑使用Nullable.Compare <T>( )静态方法 :
[code]1: int? x = null;
2: int? y = 100;
3:
4: if (Nullable.Compare(x, y) < 0)
5: {
6: //
7: Console.WriteLine("x < y");
8: }
9: else if (Nullable.Compare(x, y) > 0)
0: {
1: Console.WriteLine("x > y");
2: }
3: else
4: {
5: Console.WriteLine("x == y");
6: }
[/code]
摘要
所以,当比较两个数值而其中之一可能是一个null 时,考虑使用System.Nullable.Compare <T>( )方法,而不是比较运算符 。它会将 null 当作比任何值都小,而且使用它可以避免一些逻辑一致性问题,象 < 返回 false,>= 返回 true 等 。更多精彩的相关文章,请阅读喜乐的ASP.NET(Alex Song)
本文参考翻译自C#/.NET Little Wonders: The Nullable static class
相关文章推荐
- C# 中奇妙的函数
- C# 中奇妙的函数 -- 3. 联接序列的五种简单方法
- C# 中奇妙的函数 -- 4. Empty, DefaultIfEmpty, Count
- C# 中奇妙的函数–8. String Remove() 和 Replace()
- C# 中奇妙的函数– String Split 和 Join
- C# 中奇妙的函数–8. String Remove() 和 Replace()
- C# 中奇妙的函数之ToL“.NET研究”ookup
- 一起谈.NET技术,C# 中奇妙的函数之ToLookup
- C# 中奇妙的函数--联接序列的五种简单方法
- C# 中奇妙的函数 -- 1. ToLookup
- C#奇妙的函数(1)-五个序列聚合运算(Sum, Average, Min, Max,Aggregate)
- C#“.NET技术” 中奇妙的函数--联接序列的五种简单方法
- C# 中奇妙的函数–五个序列聚合运算(Sum, Average, Min, Max,Aggregate)
- C# 中奇妙的函数 -- 1. ToLookup
- C# 中奇妙的函数–6. 五个序列聚合运算(Sum, Average, Min, Max,Aggregate)
- C# 中奇妙的函数--联接序列的五种“.NET研究”简单方法
- 一起谈.NET技术,C# 中奇妙的函数--联接序列的五种简单方法
- C# 中奇妙的函数 -- 2. First 和 Single -- 你是她心中的第一还是唯一?
- C# 中奇妙的函数–7. String Split 和 Join
- C# 中奇妙的函数–7. String Split 和 Join