这个值真的可以为空,还是 C# 编译器只是被代码混淆了?
Can this value really ever be null, or is the C# compiler just confused by code?
我发现一些代码与 C# 8 中新的可空引用类型冲突,说我可能正在引用一个 null
,但我无法弄清楚它怎么可能为空:
https://dotnetfiddle.net/AoEMzp
public static DateTime JoinNullableDateTime(DateTime? date, DateTime? time)
{
if ((date == null) && (time == null))
return DateTime.MinValue;
else if ((date != null) && (time == null))
return date.Value.Date;
else if ((date == null) && (time != null))
return DateTime.MinValue.Add(time.Value.TimeOfDay);
else
return date.Value.Date.Add(time.Value.TimeOfDay);
}
Visual Studio 和 .NET Fiddle return 最后一行的警告:
return date.Value.Date.Add(time.Value.TimeOfDay);
.NET Fiddle
Visual Studio
所以我的问题是,任何人都可以给出 date
和 time
值的任何示例,这些值会导致此代码中的 NullReferenceException 吗?
一开始,可能的空值组合是:
date
time
Possible?
null
null
Yes
not-null
null
Yes
null
not-null
Yes
not-null
not-null
Yes
if ((date == null) && (time == null))`
return DateTime.MinValue;
此时可能的空值组合是:
date
time
Possible?
null
null
No (because we returned)
not-null
null
Yes
null
not-null
Yes
not-null
not-null
Yes
else if ((date != null) && (time == null))
return date.Value.Date;
此时可能的空值组合是:
date
time
Possible?
null
null
No (because we returned)
not-null
null
No (because we returned)
null
not-null
Yes
not-null
not-null
Yes
else if ((date == null) && (time != null))
return DateTime.MinValue.Add(time.Value.TimeOfDay);
最后可能的空性组合是:
date
time
Possible?
null
null
No (because we returned)
not-null
null
No (because we returned)
null
not-null
No (because we returned)
not-null
not-null
Yes
所以此时 不可能 日期和时间为空。两者都保证为NOT NULL
。
else
return date.Value.Date.Add(time.Value.TimeOfDay);
我看不出 date
或 time
可以在最后一行 null
的任何方式 - 但它是:
CS8629 Nullable value type may be null.
所以我错过了什么?
事实上,空值消失得更快
第一行之后
(date == null) && (time == null)
我们知道它们中的 一个 仍然有可能为空 - 但不可能两个都为空 。那么我们进行第二次检查:
(date != null) && (time == null)
在这一行之前我们知道只有一个是空的。现在我们找到了原来的那个:time
.
这意味着在第 3 行,不可能 date
成为 null
。然而我还是添加了一个检查,因为编译器告诉我这样做,而且编译器是绝对可靠的。但无论如何我都有支票:
(date == null) && (time != null)
所以即使在第三个 if
上的额外检查也是多余的。当然它在 4 日是多余的 if
。然而还有编译器。
我做错了什么?
我确定我可以 re-write the function 理解一些更难理解的东西,所以它不会让 Roslyn 感到困惑。但这不是关于这个函数,而是关于正在使用的 pattern - 如果这个模式潜伏着 NullReferenceExceptions: i想了解一下!
奖金
我与 .NET Fiddle 进行了交叉核对,以防它是我 Visual Studio 中的工件。
将您的 Visual studio 更新为 2022。
2022 不显示任何可空警告。
从 this 下载 link
代码分析器可能不够智能,无法得出您的 date
和 time
永远不能为空的结论。
您可以使用 'null forgiving' operator:
通知它这一事实
public static DateTime JoinNullableDateTime(DateTime? date, DateTime? time)
{
...
else
return date!.Value.Date.Add(time!.Value.TimeOfDay);
}
我发现一些代码与 C# 8 中新的可空引用类型冲突,说我可能正在引用一个 null
,但我无法弄清楚它怎么可能为空:
https://dotnetfiddle.net/AoEMzp
public static DateTime JoinNullableDateTime(DateTime? date, DateTime? time)
{
if ((date == null) && (time == null))
return DateTime.MinValue;
else if ((date != null) && (time == null))
return date.Value.Date;
else if ((date == null) && (time != null))
return DateTime.MinValue.Add(time.Value.TimeOfDay);
else
return date.Value.Date.Add(time.Value.TimeOfDay);
}
Visual Studio 和 .NET Fiddle return 最后一行的警告:
return date.Value.Date.Add(time.Value.TimeOfDay);
.NET Fiddle
Visual Studio
所以我的问题是,任何人都可以给出 date
和 time
值的任何示例,这些值会导致此代码中的 NullReferenceException 吗?
一开始,可能的空值组合是:
date | time | Possible? |
---|---|---|
null | null | Yes |
not-null | null | Yes |
null | not-null | Yes |
not-null | not-null | Yes |
if ((date == null) && (time == null))`
return DateTime.MinValue;
此时可能的空值组合是:
date | time | Possible? |
---|---|---|
null | null | No (because we returned) |
not-null | null | Yes |
null | not-null | Yes |
not-null | not-null | Yes |
else if ((date != null) && (time == null))
return date.Value.Date;
此时可能的空值组合是:
date | time | Possible? |
---|---|---|
null | null | No (because we returned) |
not-null | null | No (because we returned) |
null | not-null | Yes |
not-null | not-null | Yes |
else if ((date == null) && (time != null))
return DateTime.MinValue.Add(time.Value.TimeOfDay);
最后可能的空性组合是:
date | time | Possible? |
---|---|---|
null | null | No (because we returned) |
not-null | null | No (because we returned) |
null | not-null | No (because we returned) |
not-null | not-null | Yes |
所以此时 不可能 日期和时间为空。两者都保证为NOT NULL
。
else
return date.Value.Date.Add(time.Value.TimeOfDay);
我看不出 date
或 time
可以在最后一行 null
的任何方式 - 但它是:
CS8629 Nullable value type may be null.
所以我错过了什么?
事实上,空值消失得更快
第一行之后
(date == null) && (time == null)
我们知道它们中的 一个 仍然有可能为空 - 但不可能两个都为空 。那么我们进行第二次检查:
(date != null) && (time == null)
在这一行之前我们知道只有一个是空的。现在我们找到了原来的那个:time
.
这意味着在第 3 行,不可能 date
成为 null
。然而我还是添加了一个检查,因为编译器告诉我这样做,而且编译器是绝对可靠的。但无论如何我都有支票:
(date == null) && (time != null)
所以即使在第三个 if
上的额外检查也是多余的。当然它在 4 日是多余的 if
。然而还有编译器。
我做错了什么?
我确定我可以 re-write the function 理解一些更难理解的东西,所以它不会让 Roslyn 感到困惑。但这不是关于这个函数,而是关于正在使用的 pattern - 如果这个模式潜伏着 NullReferenceExceptions: i想了解一下!
奖金
我与 .NET Fiddle 进行了交叉核对,以防它是我 Visual Studio 中的工件。
将您的 Visual studio 更新为 2022。
2022 不显示任何可空警告。
从 this 下载 link
代码分析器可能不够智能,无法得出您的 date
和 time
永远不能为空的结论。
您可以使用 'null forgiving' operator:
通知它这一事实public static DateTime JoinNullableDateTime(DateTime? date, DateTime? time)
{
...
else
return date!.Value.Date.Add(time!.Value.TimeOfDay);
}