在 C# 中,是否应该检查传递给 null 的方法的引用
本文关键字:null 方法 引用 检查 是否 | 更新日期: 2023-09-27 17:55:29
嗯,几个月前我问了一个关于C和C++的类似问题,但由于整个"Windows Phone"的事情,我最近更加关注C#。
那么,在 C# 中,是否应该费心在方法边界处检查 NULL?我认为这与 C 和 C++ 中的不同,因为在 C# 中通常可以确定给定的引用是否有效——编译器将阻止在任何地方传递未初始化的引用,因此唯一可能的错误是它是空的。此外,在.NET Framework中为这些东西定义了一个特定的异常,即ArgumentNullException,它似乎编纂了程序员认为在传递无效null时应该得到什么。
我个人的观点再次是,这样做的呼叫者被破坏了,并且该呼叫者应该向他们扔NRE,直到几天结束。但是,我对此的确定程度远低于本机代码领域 - 在这方面,与C或C++相比,C#在某些地方具有完全不同的编程风格。
那么......你应该检查 C# 方法中的空参数吗?
是的,检查它们。最好使用代码协定告诉调用方您需要非空参数
void Foo(Bar bar) {
Contract.Requires(bar != null);
}
这是特别有利的,因为客户可以准确地看到参数的要求。
如果不能使用代码协定,请使用保护子句
void Foo(Bar bar) {
Guard.Against<ArgumentNullException>(bar == null);
}
快速失败。
的方法不希望特定参数为null,最好抛出一个ArgumentNullException
(或像Jason建议的那样使用合约)。通过向客户端发送合约,在调用方法时首先不传递 null 是一个更好的指标。
然后,空检查是客户的责任,这使得双方的代码更易于维护(通常是双赢的局面)......至少我是这么觉得的。
公共方法中验证所有参数是一种很好的做法。这有助于更快地定位错误,并且在读取代码时也有助于,因为它描述了方法的协定。
我们实现了一个静态类AssertUtilities
,它有一堆用于参数和状态验证的方法。我相信有些人称这样的课程为Guard
.
例如:
public static void ArgumentNotNull(object argument, string argumentName)
{
if (argument == null)
throw new ArgumentNullException(argumentName);
}
public static void ArgumentInRange(decimal argument, decimal minValue, decimal maxValue, string argumentName)
{
if (argument < minValue || argument > maxValue)
{
throw new ArgumentOutOfRangeException(
argumentName,
FormatUtilities.Format("Argument out of range: {0}. Must be between {1} and {2}.", argument, minValue, maxValue));
}
}
public static void ArgumentState(bool expression, string argumentName, string formatText, params object[] args)
{
if (!expression)
throw new ArgumentException(FormatUtilities.Format(formatText, args), argumentName);
}
public static void ArgumentHasText(string argument, string argumentName)
{
ArgumentNotNull(argument, argumentName);
ArgumentState(argument.Length > 0, argumentName, "Argument cannot be an empty string.");
}
那么......你应该检查 C# 方法中的空参数吗?
是的,当然,除非允许null
。
更好的视角:应始终检查有效的参数值。有时允许引用为空,有时必须>= 0
int
,或者字符串可能不是 NullOrWhiteSpace。
因此,最好使用参数验证块启动每个方法。
从那里开始,有几种选择。内部/私有方法的验证通常被认为不太重要,并且出于性能原因,它可以成为有条件的(甚至被排除在外)。
边界处的验证通常在发布版本中保留。几乎没有理由关闭它。
大多数项目将使用一些帮助程序类进行验证,以最大程度地减少方法中的重复编码。一个非常好但还不是很流行的工具包是内置的System.Diagnostics.Contracts类。代码协定工具具有许多有关参数验证的设置。