前段時間忙於各處奔波沒有寫博,今天想和大家再來看看一個奇妙的函數。
首先假設你不得不處理一些已有的代碼,裡面用到了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: else9: {0: Console.WriteLine("否, {0} 不小於 100.",1: x.HasValue ? x.ToString() : "null");2: }
有人可能認為要麼結果為“是”, 要麼 拋出 NullReferenceException, 對嗎? 因為一個null的整型在我們理解中是比100小,但是運行的結果為“否”!
下面的例子更加的令人費解,因為結果也為“否”:
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: }
結果使用四種比較運算符 ( <, >, <=, >= ) 全都返回否。 這個同樣適用於其他有這樣運算符定義的類型: short, float, double, DateTime, TimeSpan。
在.net 機制下 null 不是一個大數值,也不是小數值,比較時也不會發生異常。
更奇怪的事:
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: }
再看看下面的代碼:
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: }。。
解決方案: nullable 靜態類
因此,我們已經看到,<,<=,>,和>= 有一些有趣的意外行為。
但是,如果我們把null 看成是一個非常低的值應該怎麼辦?
例如,如果我們要排序一個列表。在列表中顯示的是公司當前的股票價格:
代號 描述 價位
------ ----------------------- ----------
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: }
我們也許可以簡化這個函數,但它仍然是相當凌亂!但有一個更清潔的方式做到這一點,
如果你在MSDN上 讀到 IComparer如何工作:
當使用 IComparable 時,允許將 Nothing 與任何類型進行比較,而且不會生成異常。 排序時,Nothing 被視為小於任何其他對象。
所以,我們可以改變我們的邏輯使用Nullable.Compare <T>( )靜態方法 :
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: }
摘要
所以,當比較兩個數值而其中之一可能是一個null 時,考慮使用System.Nullable.Compare <T>( )方法,而不是比較運算符 。它會將 null 當作比任何值都小,而且使用它可以避免一些邏輯一致性問題,象 < 返回 false,>= 返回 true 等 。
本文出自“喜樂的ASP.NET(Alex Song)”