在C#中,是否应该检查传递给方法的引用是否为null?
好吧,几个月前我问过,但最近由于整个“Windows Phone”的事情,我更加关注C# 那么,在C#中,是否应该费心在方法边界检查NULL?我认为这与C和C++不同,因为在C语言中通常可以确定给定的引用是否有效——编译器将阻止任何一个在任何地方传递未初始化的引用,因此唯一剩下的错误是它是空的。此外,在.NET框架中为这些东西定义了一个特定的异常,它似乎编码了当传递无效null时程序员认为应该得到的内容 我个人的观点是,打电话的人再次被打断了,并且说打电话的人应该在几天结束前都向他们扔NREs。然而,我对这个问题的把握要比我在本地代码领域中要少的多,C语言和C语言或C++语言相比,在编程方面有着不同的编程风格。在C#中,是否应该检查传递给方法的引用是否为null?,c#,arguments,nullreferenceexception,argumentnullexception,C#,Arguments,Nullreferenceexception,Argumentnullexception,好吧,几个月前我问过,但最近由于整个“Windows Phone”的事情,我更加关注C# 那么,在C#中,是否应该费心在方法边界检查NULL?我认为这与C和C++不同,因为在C语言中通常可以确定给定的引用是否有效——编译器将阻止任何一个在任何地方传递未初始化的引用,因此唯一剩下的错误是它是空的。此外,在.NET框架中为这些东西定义了一个特定的异常,它似乎编码了当传递无效null时程序员认为应该得到的内容 我个人的观点是,打电话的人再次被打断了,并且说打电话的人应该在几天结束前都向他们扔NREs。
所以。。。你应该检查C方法中的空参数吗?是的,检查它们。最好使用代码契约告诉调用方您需要非空参数
void Foo(Bar bar) {
Contract.Requires(bar != null);
}
这是特别有利的,因为客户端可以准确地看到所需的参数
如果您不能使用代码契约,请使用guard子句
void Foo(Bar bar) {
Guard.Against<ArgumentNullException>(bar == null);
}
void Foo(条形){
防范(bar==null);
}
快速失败。我认为,如果您的方法不希望某个特定参数为null,则最好抛出
ArgumentNullException
(或使用协定作为)。在调用您的方法时,契约向客户机提供了一个更好的指标,即首先不要传递null
空检查是客户端的责任,这使得双方的代码都更易于维护(通常是双赢的情况)。。。至少我是这么想的。至少在公共方法中验证所有参数是一种好的做法。这有助于更快地定位bug,并且在读取代码时也有帮助,因为它描述了方法的契约 我们实现了一个静态类AssertUtilities,它有一系列参数和状态验证方法。我相信有些人把这样的职业称为警卫 例如:
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.");
}
公共静态void ArgumentNotNull(对象参数、字符串argumentName)
{
if(参数==null)
抛出新ArgumentNullException(argumentName);
}
公共静态void ArgumentInRange(十进制参数、十进制最小值、十进制最大值、字符串argumentName)
{
if(参数<最小值| |参数>最大值)
{
抛出新ArgumentOutOfRangeException(
我的名字,
FormatUtilities.Format(“参数超出范围:{0}。必须介于{1}和{2}之间。”,参数,minValue,maxValue));
}
}
公共静态void ArgumentState(布尔表达式、字符串argumentName、字符串formatText、参数对象[]args)
{
if(!表达式)
抛出新ArgumentException(FormatUtilities.Format(formatText,args),argumentName);
}
公共静态void ArgumentHasText(字符串参数,字符串argumentName)
{
ArgumentNotNull(参数,argumentName);
ArgumentState(argument.Length>0,argumentName,“参数不能是空字符串”);
}
所以。。。你应该检查C#方法中的空参数吗
是,当然,除非允许null
更好的透视图:您应该始终检查有效的参数值。有时引用允许为null,有时int
必须=0
,或者字符串不能为null或空格
因此,以参数验证块开始每个方法是一个很好的实践
从那以后,有几个选择。对内部/私有方法的验证通常被认为不那么重要,并且出于性能原因,可以将其设置为有条件的(甚至可以忽略)
边界验证通常在发布版本中保留。几乎没有理由关掉它
大多数项目将使用一些助手类进行验证,以最小化方法内部的重复编码。内置的System.Diagnostics.Contracts类是一个非常好但还不是很流行的工具包。代码契约工具有许多关于参数验证的设置 在这里,
arguments
标记似乎有两种含义,是吗P@BoltClock:哈哈,我希望不是。我不想在这些事情上发动火战,但它们似乎无论如何都会发生。@downvoter:你对这个问题有什么特别的问题吗?willContract.Requires(bar!=null)代码>标志Foo(空)在编译时使用code>,我怀疑它会这样,在这种情况下,与使用if
的简单空检查相比,使用这样的东西有什么好处?Contract/Guard从何而来?我对那些片段不熟悉。:/这是否适用于公开的方法,还是组件内方法?@Bill ONeal:Code Contract位于.NET 4.0的System.Diagnostics.Contracts
命名空间中Guard
是一个常见的实用程序类,人们有自己的版本,但基本上,如果条件满足,它只会抛出type参数中指定的异常。@Bala R:您可以进行静态检查,它会成为文档的一部分。Contracts/Guard部分会稍微分散对答案的注意力。检查方式取决于几个因素。我喜欢合同,但它不会在任何地方都被接受(现在)。你认为这是公开库方法必须的,还是在内部也必须的?@Billy:只对公开库方法这样做。只有标记为public
的方法才能执行任何类型的参数验证。对于内部和私有方法来说,这是不必要的花费,这也是使用冰毒的原因之一