提取方法中的空验证
Null validation in extracted method
我在 .csproj
中使用 c# 8 和可空分析器
<PropertyGroup>
<Nullable>enable</Nullable>
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<RunAnalyzersDuringLiveAnalysis>true</RunAnalyzersDuringLiveAnalysis>
</PropertyGroup>
下面通过提取方法验证请求的代码显示了这样的警告:
class Program
{
public void Foo(Data request)
{
Validate(request);
request.Properties.TryGetValue("bar", out var bar);
}
private static void Validate(Data request)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
if (request.Properties == null)
{
throw new ArgumentNullException(nameof(Data.Properties));
}
}
}
public class Data
{
public Dictionary<string, string>? Properties { get; set; }
}
如果我将验证代码直接放入方法中(如下所示),则不会出现警告。
这是为什么?
如何提取验证并且没有警告?
class Program
{
public void Foo(Data request)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
if (request.Properties == null)
{
throw new ArgumentNullException(nameof(Data.Properties));
}
request.Properties.TryGetValue("bar", out var bar);
}
}
public class Data
{
public Dictionary<string, string>? Properties { get; set; }
}
我相信目前(如果你想在方法 Validation
中保持对 request
和 request.Properties
的验证)解决这个问题的唯一方法是使用 null forgiving operator
:
request.Properties!.TryGetValue("bar", out var bar);
如果您考虑从方法 Validation
中提取 request.Properties
的验证,那么您可以使用属性 NotNullAttribute
来解决问题。属性 NotNullAttribute
指定在调用 returns 时输入参数不是 null
。使用此属性,我们可以通过以下方式声明 Validate
:
private static void Validate([System.Diagnostics.CodeAnalysis.NotNull] object? obj, string name)
{
if (obj == null)
{
throw new ArgumentNullException(name);
}
}
调用此方法后 Validate
代码分析器知道 obj
不为空,并且不会对访问 obj
.
的代码产生警告
然后我们可以使用 Validate
而不会收到警告:
public static void Foo(Data request)
{
Validate(request, nameof(request));
Validate(request.Properties, nameof(request.Properties));
request.Properties.TryGetValue("bar", out var bar);
}
我在 .csproj
<PropertyGroup>
<Nullable>enable</Nullable>
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<RunAnalyzersDuringLiveAnalysis>true</RunAnalyzersDuringLiveAnalysis>
</PropertyGroup>
下面通过提取方法验证请求的代码显示了这样的警告:
class Program
{
public void Foo(Data request)
{
Validate(request);
request.Properties.TryGetValue("bar", out var bar);
}
private static void Validate(Data request)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
if (request.Properties == null)
{
throw new ArgumentNullException(nameof(Data.Properties));
}
}
}
public class Data
{
public Dictionary<string, string>? Properties { get; set; }
}
如果我将验证代码直接放入方法中(如下所示),则不会出现警告。
这是为什么?
如何提取验证并且没有警告?
class Program
{
public void Foo(Data request)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
if (request.Properties == null)
{
throw new ArgumentNullException(nameof(Data.Properties));
}
request.Properties.TryGetValue("bar", out var bar);
}
}
public class Data
{
public Dictionary<string, string>? Properties { get; set; }
}
我相信目前(如果你想在方法 Validation
中保持对 request
和 request.Properties
的验证)解决这个问题的唯一方法是使用 null forgiving operator
:
request.Properties!.TryGetValue("bar", out var bar);
如果您考虑从方法 Validation
中提取 request.Properties
的验证,那么您可以使用属性 NotNullAttribute
来解决问题。属性 NotNullAttribute
指定在调用 returns 时输入参数不是 null
。使用此属性,我们可以通过以下方式声明 Validate
:
private static void Validate([System.Diagnostics.CodeAnalysis.NotNull] object? obj, string name)
{
if (obj == null)
{
throw new ArgumentNullException(name);
}
}
调用此方法后 Validate
代码分析器知道 obj
不为空,并且不会对访问 obj
.
然后我们可以使用 Validate
而不会收到警告:
public static void Foo(Data request)
{
Validate(request, nameof(request));
Validate(request.Properties, nameof(request.Properties));
request.Properties.TryGetValue("bar", out var bar);
}