具有可为空的DateTimeOffset

时间:2016-09-24 20:05:35

标签: c# .net c#-6.0 datetimeoffset null-conditional-operator

环境: Visual Studio 2015

TimeZone::UTC + 7:00,曼谷

问题:在DateTimeOffset可以为空的varialbe(DateTimeOffset?)上,使用Null Conditional运算符会导致异常,即即使值为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

enter image description here

修改

我知道有很多方法可以修复代码,即

    DateTime dateTimeMinimum = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);

这是我的查询,当我不使用空条件运算符

var a1 = value as DateTimeOffset?;

不会导致异常。是因为null条件运算符会在每个后续博客

中展开变量

http://www.ninjacrab.com/2016/09/11/c-how-the-null-conditional-operator-works-with-nullable-types/

我更感兴趣的是理解为什么它在我使用null条件运算符时会中断,并且当我使用' as'运算符而不使用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);
        }

2 个答案:

答案 0 :(得分:1)

问题是最小日期是UTC 0,所以如果你想要那个但是具有正的UTC ,这意味着在UTC 0它将早于最小可能{{1 }}

简单地说,你不能创建它(最小日期UTC +1):

DateTime

因为这会在12月31日 -0001 11:00 PM UTC创建new DateTimeOffset(DateTime.MinValue, new TimeSpan(1, 0, 0))

异常发生在这里:

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(); 没有被执行而且永远不会,而且我所说的一直失败的是从最小ToLocalTimeDateTime的演员阵容时区。

顺便说一句,您不能只使用DateTimeOffset运算符将DateTime转换为DateTimeOffset?;总是会返回null。该运算符用于兼容的clases。

最后,即使解决这个问题,我认为您的代码也很难理解和维护。你到底想干什么?

答案 1 :(得分:0)

这与可空操作符无关。

这会导致同样的错误:

var dto2 = new DateTimeOffset(dateTimeMinimum);

使用DateTime.Min时偏移量太大,如果将其更改为DateTime.Now,则代码将起作用。