为什么 Visual Studio 不警告我空引用异常?
Why doesn't Visual Studio warn me about a null reference exception?
不知为什么Visual Studio2019不吐槽这段C#代码:
dynamic deserializedBody = JsonConvert.DeserializeObject(requestBody);
deserializedBody?.date.ToString();
由于 deserializedBody?.date
可能是 null
,这意味着 ToString
方法将应用于某些 null
。我认为是这样的:
deserializedBody?.date?.ToString();
将是正确的使用形式,但 Visual Studio 不会抱怨第一个版本。我肯定错过了这段代码的真实本质。
null 安全取消引用运算符在遇到 null 时立即停止对整个表达式的求值。因此,如果 deserializedBody
为 null,它不会尝试计算 date
,也不会调用 ToString()
任何东西 - 所以你不会得到异常。
完整示例:
using System;
class Test
{
DateTime date = DateTime.UtcNow;
static void Main()
{
Test t = null;
// No exception thrown
Console.WriteLine(t?.date.ToString());
}
}
这里的表达式t?.date.ToString()
等同于:
t is null ? null : t.date.ToString()
(除了 t
只计算一次)。 不等同于
(t is null ? null : t.date).ToString()
...这就是我怀疑您期望它做的事情。
但是不,这个 不会 防止 deserializedBody
为非空,但 deserializedBody.date
为空的情况。
如果您期望由于 C# 8 可为 null 的引用类型而收到警告,我相信动态表达式永远不会进行 null 检查。例如,请考虑:
class Test
{
public string? foo;
}
class Program
{
static void Main(string[] args)
{
Test t = new Test();
dynamic d = t;
Console.WriteLine(t.foo.Length); // Warning
Console.WriteLine(d.foo.Length); // No warning
Console.WriteLine(d.bar); // No warning for this either
}
}
我怀疑这是因为编译器基本上没有关于d.foo
是什么的信息。对于每一个有有用警告的情况,都会有另一种情况警告没有用。当您处于动态类型领域时,您已经接受了一定程度的风险 - 当 d.foo
的访问一开始就有风险时,警告取消引用 d.foo
是有风险的似乎很奇怪。
不知为什么Visual Studio2019不吐槽这段C#代码:
dynamic deserializedBody = JsonConvert.DeserializeObject(requestBody);
deserializedBody?.date.ToString();
由于 deserializedBody?.date
可能是 null
,这意味着 ToString
方法将应用于某些 null
。我认为是这样的:
deserializedBody?.date?.ToString();
将是正确的使用形式,但 Visual Studio 不会抱怨第一个版本。我肯定错过了这段代码的真实本质。
null 安全取消引用运算符在遇到 null 时立即停止对整个表达式的求值。因此,如果 deserializedBody
为 null,它不会尝试计算 date
,也不会调用 ToString()
任何东西 - 所以你不会得到异常。
完整示例:
using System;
class Test
{
DateTime date = DateTime.UtcNow;
static void Main()
{
Test t = null;
// No exception thrown
Console.WriteLine(t?.date.ToString());
}
}
这里的表达式t?.date.ToString()
等同于:
t is null ? null : t.date.ToString()
(除了 t
只计算一次)。 不等同于
(t is null ? null : t.date).ToString()
...这就是我怀疑您期望它做的事情。
但是不,这个 不会 防止 deserializedBody
为非空,但 deserializedBody.date
为空的情况。
如果您期望由于 C# 8 可为 null 的引用类型而收到警告,我相信动态表达式永远不会进行 null 检查。例如,请考虑:
class Test
{
public string? foo;
}
class Program
{
static void Main(string[] args)
{
Test t = new Test();
dynamic d = t;
Console.WriteLine(t.foo.Length); // Warning
Console.WriteLine(d.foo.Length); // No warning
Console.WriteLine(d.bar); // No warning for this either
}
}
我怀疑这是因为编译器基本上没有关于d.foo
是什么的信息。对于每一个有有用警告的情况,都会有另一种情况警告没有用。当您处于动态类型领域时,您已经接受了一定程度的风险 - 当 d.foo
的访问一开始就有风险时,警告取消引用 d.foo
是有风险的似乎很奇怪。