C# 中奇妙的函數(shù)–5. Nullable 靜態(tài)類
前段時間忙于各處奔波沒有寫博,今天想和大家再來看看一個奇妙的函數(shù)。
首先假設(shè)你不得不處理一些已有的代碼,里面用到了nullable(可空值類型)的變量, 你必須要用這變量與不可空變量比較.
使用 <, >, <=, >= 來比較 nullable 值
看下面的代碼:
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: }
有人可能認為要么結(jié)果為“是”, 要么 拋出 NullReferenceException, 對嗎? 因為一個null的整型在我們理解中是比100小,但是運行的結(jié)果為“否”!
下面的例子更加的令人費解,因為結(jié)果也為“否”:
1: int? x = null;
2:
3: if (x < int.MaxValue)
4: {
5: // ...
6: }
那么,我們說 null 小于所有的有效整型, 對嗎? 如果對的話,你怎么看這段代碼:
1: int? x = null;
2:
3: // 等等,X 不小于MinValue?
4: if (x < int.MinValue)
5: {
6: // ...
7: }
如果我們使用大于符號判斷時:
1: int? x = null;
2:
3: // x 也不大于MinValue….
4: if (x > int.MinValue)
5: {
6: // ...
7: }
結(jié)果使用四種比較運算符 ( <, >, <=, >= ) 全都返回否。 這個同樣適用于其他有這樣運算符定義的類型: short, float, double, DateTime, TimeSpan。
在.net 機制下 null 不是一個大數(shù)值,也不是小數(shù)值,比較時也不會發(fā)生異常。
更奇怪的事:
1: DateTime? x = null;
2: DateTime? y = null;
3:
4: if (x <= y)
5: {
6: Console.WriteLine("你覺得他們相等嗎?");
7: }
8: else
9: {
10: Console.WriteLine("結(jié)果不是:<=, <, >, >= 根本不適用于null.");
11: }
再看看下面的代碼:
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: // 這個才是我們得到的結(jié)果
15: Console.WriteLine("X 等于 Y");
16: }
解決方案: nullable 靜態(tài)類
因此,我們已經(jīng)看到,<,<=,>,和>= 有一些有趣的意外行為。
但是,如果我們把null 看成是一個非常低的值應(yīng)該怎么辦?
例如,如果我們要排序一個列表。在列表中顯示的是公司當前的股票價格:
代號 描述 價位
------ ----------------------- ----------
ABCZ Apples and Oranges Inc n/a
XYZP Zippers and Buttons Inc 1.57
AZAZ Carrots and Turnips Inc 23.13
比較運算符不適用于 null,因此,我們不得不做一些非常復雜的邏輯,如:
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: }
我們也許可以簡化這個函數(shù),但它仍然是相當凌亂!但有一個更清潔的方式做到這一點,
如果你在MSDN上 讀到 IComparer如何工作:
當使用 IComparable 時,允許將 Nothing 與任何類型進行比較,而且不會生成異常。 排序時,Nothing 被視為小于任何其他對象。
所以,我們可以改變我們的邏輯使用Nullable.Compare <T>( )靜態(tài)方法 :
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: }
摘要
所以,當比較兩個數(shù)值而其中之一可能是一個null 時,考慮使用System.Nullable.Compare <T>( )方法,而不是比較運算符 。它會將 null 當作比任何值都小,而且使用它可以避免一些邏輯一致性問題,象 < 返回 false,>= 返回 true 等 。

浙公網(wǎng)安備 33010602011771號