[英]Null conditional operator with nullable DateTimeOffset
環境: Visual Studio 2015
時區:: UTC + 7:00,曼谷
問題 :在DateTimeOffset可為空的varialbe(DateTimeOffset?)上,使用Null條件運算符會導致異常,即,即使值是NULL,它仍然會調用該方法,即(值如DateTimeOffset?)?. ToLocalTime(),它會調用ToLocalTime和結果例外。
查詢 :我可以通過不使用Null條件運算符或使用GetValueOrDefault而不是運算符來解決該問題,但我想了解為什么它在所有UTC + TimeZones例外的情況下重新輸出,所以它與UTC-TimeZones一起很好地工作
碼:
var dateTimeMinimum = DateTime.MinValue;
var value = (object)dateTimeMinimum; // Mimic the WPF converter behavior
var a1 = value as DateTimeOffset?; // This works
if (a1 != null)// This works as it won't execute the code in the 'if'loop
{
var b1 = (a1 as DateTimeOffset?)?.ToLocalTime();
}
var dto = (value as DateTimeOffset?)?.ToLocalTime() ?? (DateTime)value;// This breaks with following exception
編輯 :
我知道有很多方法可以修復代碼,即
DateTime dateTimeMinimum = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
當我不使用空條件運算符時,這是我的查詢
var a1 = value as DateTimeOffset?;
它不會導致異常。 是因為空條件運算符會在隨后的博客中解包變量
http://www.ninjacrab.com/2016/09/11/c-how-the-null-conditional-operator-works-with-nullable-types/
我對理解為什么在使用null條件運算符時會中斷而在使用(as)運算符而不使用DateTimeKind.Utc進行簡單強制轉換時會起作用的原因更感興趣
編輯2 :
這是DateTimeOffset(.NET框架代碼)的構造函數,它在ValidateOffset方法處中斷。 來源-http : //referencesource.microsoft.com/#mscorlib/system/datetimeoffset.cs,68b4bb83ce8d1c31
// Constructs a DateTimeOffset from a DateTime. For Local and Unspecified kinds,
// extracts the local offset. For UTC, creates a UTC instance with a zero offset.
public DateTimeOffset(DateTime dateTime) {
TimeSpan offset;
if (dateTime.Kind != DateTimeKind.Utc) {
// Local and Unspecified are both treated as Local
offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
}
else {
offset = new TimeSpan(0);
}
m_offsetMinutes = ValidateOffset(offset);
m_dateTime = ValidateDate(dateTime, offset);
}
問題在於,最小日期為UTC 0,因此,如果您希望UTC為正 ,而UTC為正 ,則意味着在UTC 0時,它將早於最小DateTime
。
簡而言之,您無法創建此代碼(最低日期UTC +1):
new DateTimeOffset(DateTime.MinValue, new TimeSpan(1, 0, 0))
因為這會為UTC 12月31日-0001 11:00 PM創建DateTimeOffset
。
異常恰好發生在這里:
var dto = <something null> ?? (DateTime)value;
由於dto
推斷為DateTimeOffset
,因此您正在執行(DateTimeOffset)(DateTime)value
,然后就是拋出異常時。 該強制轉換嘗試創建無法表示的否定日期。
嘗試使用以下代碼來確認問題與空變量無關 :
var dateTimeMinimum = DateTime.MinValue;
var value = (object)dateTimeMinimum; // Mimic the WPF converter behavior
DateTimeOffset dto = (DateTime)value;
更新
由於您仍然不相信我,請嘗試以下操作:
var dto = (value as DateTimeOffset?)?.ToLocalTime() ?? new DateTimeOffset();
這不會失敗。 為什么? 因為ToLocalTime
未被執行且從未執行過 ,並且一直失敗,這就是我告訴您的,所以從最小DateTime
到具有正時區的DateTime
進行了DateTimeOffset
。
順便說一句,您不能僅將DateTime
轉換為DateTimeOffset?
與as
運算符; 它將始終返回null。 該運算符用於兼容的句柄。
最后,即使解決此問題,我認為您的代碼也很難理解和維護。 您到底要在這里做什么?
這與可為空的運算符無關。
這將導致相同的錯誤:
var dto2 = new DateTimeOffset(dateTimeMinimum);
使用DateTime.Min時,偏移量太大,如果將其更改為DateTime.Now,代碼將起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.