2013-08-12 63 views
2

小問題,只是爲了理解:我有2個可爲空的日期時間。我讀出創建時間和更新時間,兩者都可以填充。所以,我要檢查這就是後來的:?可空類型的構造函數處理

lastChangedIndrole = (tmpCreate > tmpUpdate ? tmpCreate : tmpUpdate); 

但是在這裏發生一些奇怪的事情。 f.e.當我想要拋出一個錯誤。 tmpUpdate爲null,但它似乎會返回一些內容,但不是返回值,而是第二個,在我的示例中是更新。

有什麼我不明白的嗎?我認爲代碼將檢查毫秒爲1900,如果有空值,則會拋出錯誤。但是這沒有發生。那是我不明白的一些魔法嗎?

P.S. :有沒有特別的詞? vb中的IIF構造函數?很難搜索到某些東西。當Nullable.Value

感謝,並在本週

馬蒂亞斯

+0

*爲什麼*你會指望拋出異常?請注意,您正在討論的代碼中沒有構造函數。你只是指「條件操作符」而不是「構造函數」? –

+0

您可能也有興趣檢查值是否爲'null'或等於'DateTime.MinValue',在將操作結果分配給另一個變量之前確保數據是有效的非常重要(導致另一個奇怪的行爲並且很難調試)。 – glautrou

+0

我認爲你的意思是使用「構造」這個詞,而不是「構造函數」,因爲後一個詞在.NET和C#中(並且確實有很多編程語言)具有特殊含義,而「構造」是指由小部分,或彙編術語和想法而構成的陳述/句子。 –

回答

1

你可以比較兩個DateTime?對象,但大多數時候,當操作數中至少有一個是null,其結果將是false

例如:

DateTime? today = DateTime.Today; 
DateTime? yesterday = DateTime.Today.AddDays(-1); 
DateTime? nodate = null; 
DateTime? nodate2 = null; 

Console.WriteLine(today > yesterday); //true 
Console.WriteLine(today < yesterday); //false 

Console.WriteLine(today > nodate); //false 
Console.WriteLine(today == nodate); //false 
Console.WriteLine(today < nodate); //false 

Console.WriteLine(nodate > yesterday); //false 
Console.WriteLine(nodate == yesterday); //false 
Console.WriteLine(nodate < yesterday); //false 

Console.WriteLine(nodate > nodate2); //false 
Console.WriteLine(nodate == nodate2); //true - this is the exception 
Console.WriteLine(nodate < nodate2); //false 

我會建議避免太巧了,是在代碼中更明確:

if (tmpUpdate.HasValue) 
{ 
    if (tmpCreate.HasValue) 
    { 
     lastChangedIndrole = (tmpCreate > tmpUpdate ? tmpCreate : tmpUpdate); 
    } 
    else 
    { 
     lastChangedIndrole = tmpUpdate; 
    } 
} 
else 
{ 
    if (tmpCreate.HasValue) 
    { 
     lastChangedIndrole = tmpCreate; 
    } 
    else 
    { 
     lastChangedIndrole = null; 
    } 
} 
+0

非常感謝,我只是確保這些值不爲空時,所以我不能遇到這個問題。 –

3

可空類型爲空一個良好的開端拋出異常。但它不會拋出異常,但它會給出意想不到的結果(比較null與非空值永不返回真)。

下面將舉例問題

DateTime? dt1 = null; 
DateTime? dt2 = DateTime.Now; 

bool b1 = dt2 > dt1;//false(we expect true here) 
bool b2 = dt2 < dt1;//false 
bool b3 = dt2 == dt1;//false 

這種行爲被記錄在案Here

當您執行的比較可空類型,如果可空類型之一的值是零,而另一不是,除了!=(不等於)之外,所有比較的結果均爲false。重要的是不要假設因爲特定的比較返回錯誤,相反的情況返回true。在以下示例中,10不大於,小於或等於null。只有num1!= num2的計算結果爲true。

3

C#提起<>運營商在可空類型,以及他們返回false如果其中一個參數爲空。

因此tmpCreate > tmpUpdate的計算結果爲false如果tmpCreatetmpUpdate爲空。

它在本說明書中被描述:

7.3.7擡升運營

•對於關係運算符<> < => =存在如果操作數的 符的提升形式類型都是非空值類型 並且結果類型是bool。解除表格由 構建,添加單個?修飾符到每個操作數類型。解除操作員 如果一個或兩個操作數都爲空,則會生成值false。否則, 解除運算符解開操作數,並應用底層 運算符生成布爾結果。

+0

'((int?)null)==((int?)null)'=='true' 。我討厭空比較:-)爲他們建立真相表是令人頭痛的水平。 – xanatos

+0

@xanatos - 是的,你說的對== ==。我已經刪除它,因爲它與此問題無關。 – Lee

+0

有意思......'<=' and '> ='完全解除了......所以'null == null',但是!'null <= null' – xanatos

1

當你比較空的值,無論是到其他空的值,或對於非空值,非空類型的操作符被「解除」,因此也適用於它們的可空對象。

但是,特殊處理將處理其中一個或兩個都爲空的情況。

這裏有一個LINQPad例如:

void Main() 
{ 
    int? a = 10; 
    int? b = null; 

    (a > b).Dump(); 
    (b > a).Dump(); 
    (a == b).Dump(); 
    (a != b).Dump(); 
} 

輸出:

False 
False 
False 
True 

正如你所看到的,比較兩個null的整數,其中一個是null,只有平等的運營商時,其產生預期的結果。

如果我們使a變量非空的INT:

int a = 10; 

但在其他方面保持代碼,然後它會產生同樣的結果。

如果兩者均爲空,該怎麼辦?

int? a = null; 
int? b = null; 

產地:

False 
False 
True 
False 

結論:

  • 相等運算符(==!=)正確處理null s的空類型
  • 比大於運營商小於或大於沒有,如果其中一個操作數是,它們將返回,即使您切換比較。基本上,10既不小於也不大於null

如果試圖讀取null可空類型值的.Value屬性,它會拋出一個異常,但運營商不直接去爲.Value屬性,但首先檢查.HasValue屬性,然後處理這些在嘗試實際比較之前的案例。

1

使用^(xor)檢查是否只有一個條件爲真(等於null),則返回第一個非空值,然後返回??。如果兩者都不爲空,則使用您現有的表達式。

if (tmpCreate == null^tmpUpdate == null) 
    lastChangedIndrole = tmpCreate ?? tmpUpdate; 
else 
    lastChangedIndrole = (tmpCreate > tmpUpdate ? tmpCreate : tmpUpdate); 

但你也可以選擇第一個非空值直接分配,然後覆蓋它,如果tmpUpdate是大於值:

lastChangedInRole = tmpCreate ?? tmpUpdate; 
if (tmpUpdate > lastChangedInRole) 
    lastChangedInRole = tmpUpdate; 

(理由:如果只有一個有值,比較永遠是假的和非空值將使用??進行分配,否則tmpCreated將被分配,這是唯一的neccessary比較它tmpUpdate

1

使用^(XOR),以檢查是否只有一個康迪重刑是真實的(等於空),然後??返回第一個非空值。如果兩者都不爲空,則使用您現有的表達式。

if(tmpCreate == null^tmpUpdate == null) lastChangedIndrole = tmpCreate ?? tmpUpdate; else lastChangedIndrole =(tmpCreate> tmpUpdate?tmpCreate:tmpUpdate);