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