c# - 验证公共(public)/私有(private)方法的函数参数时的最佳实践

标签 c# validation

<分区>

做一些研究,似乎人们普遍认为应该验证公共(public)方法的参数,而私有(private)函数通常不需要。这让我产生了一些疑问,但到目前为止我还没有找到满意的答案。

例子:

public void DoSomething(int i)
{
    if (i < 0)
        throw new ArgumentOutOfRangeException("i");

    double d = DoWork(i);
}

private double DoWork(int i)
{
    double ret = ...; // some calculation
    return ret;
}

想法:

  1. 如果 i 的要求在 DoWork() 内部发生非负变化怎么办?该设计存在遗留过时验证检查的风险。我知道,程序员负责调整已更改函数的用法,但这让我想知道是否有更好的方法来最大程度地降低错误风险。

  2. DoWork() 不是来自 DoSomething() 的不同调用怎么样?我们必须冗余地验证参数吗?

public void DoSomething(int i)
{
    if (i < 0)
        throw new ArgumentOutOfRangeException("i");

    double d = DoWork(i);
}

public void DoSomethingElse()
{
    int i = 5;
    if (i < 0)
        throw new ArgumentOutOfRangeException("i");

    double d = DoWork(i);
}

private double DoWork(int i)
{
    double ret = ...; // some calculation
    return ret;
}

这可以通过将检查放入它自己的函数中来稍微清理一下。然后存在调用 DoWork(int i) 的新函数将忘记验证 i 的风险。

public void DoSomething(int i)
{
    ThrowIfIntegerIsNegative(i);

    double d = DoWork(i);
}

public void DoSomethingElse()
{
    int i = 5;
    ThrowIfIntegerIsNegative(i);

    double d = DoWork(i);
}

static void ThrowIfIntegerIsNegative(int i)
{
    if (i < 0)
        throw new ArgumentOutOfRangeException("i");
}

private double DoWork(int i)
{
    double ret = ...; // some calculation
    return ret;
}

那比这更好吗?

public void DoSomething(int i)
{
    double d = DoWork(i);
}

public void DoSomethingElse()
{
    double d = DoWork(5);
}

private double DoWork(int i)
{
    if (i < 0)
        throw new ArgumentOutOfRangeException("i");

    double ret = ...; // some calculation
    return ret;
}

根据情况,这些是我试图同时实现的一些目标:

  1. 在一个地方进行参数验证(并且可能在使用参数的函数内部)
  2. 尽早报告错误(可能不想让一堆代码运行一个小时只是为了在最后因一些错误的用户输入而失败)
  3. 避免多次验证参数
  4. 避免发布代码中的性能影响

您如何取得平衡?哪种方法最适合您?我将不胜感激任何见解。

最佳答案

验证公共(public)方法中的参数而不验证私有(private)方法中的参数背后的逻辑大致如下:

  • When a public method is called with invalid arguments, it is a programming error outside your control.
  • When a non-public method is called with invalid arguments, it is a logical error within your control.

这个逻辑是合理的:不需要浪费周期来验证模块内部生成的方法的参数。另一方面,私有(private)方法可以始终假定它们的参数有效,因为您可以控制对私有(private)方法的所有调用。

但是,捕捉违反这些假设的情况是非常有益的。为此,使用运行时断言代替私有(private)方法中的参数验证是一个非常好的主意。这会捕获来自外部调用者的无效调用并出现异常,并提醒您来自您自己的带有断言的方法的无效调用。

关于c# - 验证公共(public)/私有(private)方法的函数参数时的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16969228/

相关文章:

c# - 如何使用 DataAnnotation 属性在控制台应用程序中验证模型

c# - Rhino-Etl 和 MySQL 的问题

php - Symfony 2 登录验证

java - 如何在自定义 JSR-303 Bean 验证约束中使用 session 属性(验证码)?

rest - 从Grails命令对象验证返回特定的HTTP错误代码

c# - 在 ItemsControl 中滚动,同时使用水平 StackPanel 作为 ItemsPanel

c# - 为什么 IDictionary<TKey,TValue> 不/不能实现 ILookup<TKey,TValue>?

c# - 在 asp.net core 2 graphql 端点的情况下,如何提取请求 header 并将其传递给业务逻辑?

validation - 我们可以在Struts2字段表达式中调用带有参数的方法吗?

matlab - 为什么 MATLAB 会尝试实例化抽象属性?