簡體   English   中英

具有空的DateTimeOffset的空條件運算符

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM