11

好吧,几个月前我问了一个关于 C 和 C++ 的类似问题,但由于整个“Windows Phone”的事情,我最近更加关注 C#。

那么,在 C# 中,是否应该费心检查方法边界处的 NULL 值?我认为这与 C 和 C++ 不同,因为在 C# 中,通常可以确定给定的引用是否有效——编译器会阻止将未初始化的引用传递到任何地方,因此唯一剩下的可能错误是它为 null . 此外,在 .NET Framework 中为这些事情定义了一个特定的异常,即ArgumentNullException,它似乎编纂了程序员认为在传递无效 null 时他们应该得到的内容。

我个人的意见是,这样做的呼叫者再次被破坏,并且说呼叫者应该向他们抛出 NRE,直到天结束。但是,与在本机代码领域相比,我对此的确定要少得多——在这方面,与 C 或 C++ 相比,C# 在某些地方具有完全不同的编程风格。

那么...您应该检查 C# 方法中的空参数吗?

4

4 回答 4

8

是的,检查他们。最好使用代码契约告诉调用者您需要非空参数

void Foo(Bar bar) {
    Contract.Requires(bar != null);
}

这是特别有利的,因为客户端可以准确地看到所需的参数。

如果您不能使用代码合同,请使用保护条款

void Foo(Bar bar) {
    Guard.Against<ArgumentNullException>(bar == null);
}

快速失败。

于 2011-05-07T04:12:31.173 回答
5

如果您的方法不希望特定参数为空,我认为最好抛出ArgumentNullException(或使用Jason 建议的合同)。在调用您的方法时,合同首先向客户表明不要传递 null ,这是一个更好的指标。

空值检查是客户的责任,这使得双方的代码更易于维护通常是双赢的情况)......至少我是这么认为的。

于 2011-05-07T04:13:04.803 回答
3

至少在公共方法中验证所有参数是一种很好的做法。这有助于更快地定位错误,也有助于阅读代码,因为它描述了方法的契约。

我们实现了一个静态类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.");
    }
于 2011-05-07T04:47:51.640 回答
2

那么...您应该检查 C# 方法中的空参数吗?

是的,当然,除非null是允许的。

更好的视角:您应该始终检查有效的参数值。有时允许引用为空,有时int必须是>= 0或字符串可能不是 NullOrWhiteSpace。

因此,使用参数验证块开始每个方法是一个很好的做法。

从那里开始有几个选择。内部/私有方法的验证通常被认为不太重要,并且出于性能原因,它可以是有条件的(甚至可以省略)。

边界验证通常保留在发布版本中。几乎没有理由将其关闭。

大多数项目将使用一些辅助类进行验证,以尽量减少方法内的重复编码。一个很好但还不是很流行的工具包是内置的 System.Diagnostics.Contracts 类。Code-Contracts 工具有许多关于参数验证的设置。

于 2011-05-07T08:05:23.307 回答