2016-09-24 35 views
0

環境:的Visual Studio 2015年空條件操作可空的DateTimeOffset

區::UTC + 7:00,曼谷

問題:在可空的DateTimeOffset varialbe(?的DateTimeOffset)時,使用NULL條件運算符會導致異常,即它仍然調用該方法,即使該值爲NULL,即(值爲DateTimeOffset?)?ToLocalTime(),它將調用ToLocalTime並導致異常。

查詢:我可以不使用空有條件的經營者或使用GetValueOrDefault,而不是運營商的解決這個問題,但我想知道爲什麼它在所有UTC +時區異常resutls,它與UTC效果很好 - 時區

代碼:

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 

enter image description here

編輯

我知道有很多方法來修復代碼,即

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/

我更感興趣的是理解爲什麼它打破了,當我用空條件運算符和作品時,我如果使用「作爲」操作簡單的投不使用DateTimeKind.Utc

EDIT2

這是的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); 
     } 
+0

拋出異常時偏移的值是多少?錯誤消息似乎表明結果的年份是小於0或大於10K – pquest

+0

DateTime.MinValue –

+0

這是偏移量的值? – pquest

回答

1

的問題是,最小的日期是UTC 0,所以如果你想要的是而是以積極的UTC,這意味着在UTC 0它會比最小可能DateTime更早。

簡單地說,您不能創建(最小日期UTC +1):

new DateTimeOffset(DateTime.MinValue, new TimeSpan(1, 0, 0)) 

,因爲這會爲12月31日-0001下午11:00 UTC創建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; 

UPDATE

正如你還是不相信我的話,試試這個:

var dto = (value as DateTimeOffset?)?.ToLocalTime() ?? new DateTimeOffset(); 

這不會失敗。爲什麼?因爲ToLocalTime沒有執行,也沒有執行過,而這次失敗的是我告訴你的,從最小DateTimeDateTimeOffset的演員陣容都帶有積極的時區。


順便說一句,你不能只是轉換DateTimeDateTimeOffset?as操作;那將始終返回null。該運算符用於兼容的類。

最後,即使解決這個問題,我認爲你的代碼太難理解和維護。你到底想在這裏做什麼?

+0

那就是我想要的NULL值,並且我使用了Null條件操作符。如果那是空的,我試圖解析它到DateTime。 –

+0

var dto =(值爲DateTimeOffset?)?ToLocalTime()? (日期時間)值; –

+0

但它不爲空,你會得到一個異常... UTC最小日期時間轉換爲本地時間(UTC +7)引發該異常。沒有空問題相關。 – Andrew

0

這有什麼好做的可空操作。

這會導致同樣的錯誤:

var dto2 = new DateTimeOffset(dateTimeMinimum); 

偏移使用DateTime.Min時,如果將其更改爲DateTime.Now太大,你的代碼將工作。

+0

感謝您的回覆。如果您在我的代碼中看到a1變量,則會生成NULL值,然後在塊中執行不會進入。如果將「value」變量轉換爲DateTimeOffset ?,它應該是NULL,它不應該導致異常。 –

+0

在這種情況下,as運算符將始終返回NULL,因爲您試圖在不相關的類的DateTime和DateTimeOffset之間進行轉換,而NULL運算符試圖獲取該值。我不熟悉Roslyn空操作符的「幕後」,但我相信你的行的行爲像顯式轉換 –