具有可为空 DateTimeOffset 的空条件运算符
Null conditional operator with nullable DateTimeOffset
环境: Visual Studio 2015
时区::UTC + 7:00,曼谷
问题:在 DateTimeOffset 可空变量(DateTimeOffset?)上,使用 Null 条件运算符会导致异常,即即使值为 NULL,它仍会调用该方法,即(值作为 DateTimeOffset?)?.ToLocalTime(),它调用 ToLocalTime 并导致异常。
Query:我可以通过不使用 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);
这是我的查询,当我不使用 null 条件运算符时
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);
}
这与可空运算符无关。
这会导致同样的错误:
var dto2 = new DateTimeOffset(dateTimeMinimum);
使用 DateTime.Min 时偏移太大,如果将其更改为 DateTime.Now,您的代码将起作用。
问题是最短日期在 UTC 0,所以如果你想要那个 但 UTC 为正 ,这意味着在 UTC 0 它将早于最小可能 DateTime
.
简而言之,您无法创建此(最小日期 UTC +1):
new DateTimeOffset(DateTime.MinValue, new TimeSpan(1, 0, 0))
因为这将为 12 月 31 日 -0001 11:00PM 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;
更新
你还不相信我,试试这个:
var dto = (value as DateTimeOffset?)?.ToLocalTime() ?? new DateTimeOffset();
这不会失败。为什么?因为 ToLocalTime
没有被执行而且从来没有被执行 ,而一直失败的是我告诉你的,从最小值 DateTime
到 [=15= 的转换] 正时区。
顺便说一句,您不能只使用 as
运算符将 DateTime
转换为 DateTimeOffset?
;那将始终 return 为空。该运算符用于兼容类。
最后,即使修复了这个问题,我也觉得你的代码太难理解和维护了。你到底想在这里做什么?
环境: Visual Studio 2015
时区::UTC + 7:00,曼谷
问题:在 DateTimeOffset 可空变量(DateTimeOffset?)上,使用 Null 条件运算符会导致异常,即即使值为 NULL,它仍会调用该方法,即(值作为 DateTimeOffset?)?.ToLocalTime(),它调用 ToLocalTime 并导致异常。
Query:我可以通过不使用 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);
这是我的查询,当我不使用 null 条件运算符时
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);
}
这与可空运算符无关。
这会导致同样的错误:
var dto2 = new DateTimeOffset(dateTimeMinimum);
使用 DateTime.Min 时偏移太大,如果将其更改为 DateTime.Now,您的代码将起作用。
问题是最短日期在 UTC 0,所以如果你想要那个 但 UTC 为正 ,这意味着在 UTC 0 它将早于最小可能 DateTime
.
简而言之,您无法创建此(最小日期 UTC +1):
new DateTimeOffset(DateTime.MinValue, new TimeSpan(1, 0, 0))
因为这将为 12 月 31 日 -0001 11:00PM 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;
更新
你还不相信我,试试这个:
var dto = (value as DateTimeOffset?)?.ToLocalTime() ?? new DateTimeOffset();
这不会失败。为什么?因为 ToLocalTime
没有被执行而且从来没有被执行 ,而一直失败的是我告诉你的,从最小值 DateTime
到 [=15= 的转换] 正时区。
顺便说一句,您不能只使用 as
运算符将 DateTime
转换为 DateTimeOffset?
;那将始终 return 为空。该运算符用于兼容类。
最后,即使修复了这个问题,我也觉得你的代码太难理解和维护了。你到底想在这里做什么?