繁体   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