2016-09-24 134 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空操作符的“幕后”,但我相信你的行的行为像显式转换 –