【问题标题】:Faster way to perform checks on method arguments对方法参数执行检查的更快方法
【发布时间】:2011-02-07 13:29:03
【问题描述】:

这主要是出于好奇,可能是一个愚蠢的问题。 :)

我有这样的方法:

public void MyMethod(string arg1, string arg2, int arg3, string arg4, MyClass arg5)
{
    // some magic here
}

任何参数都不能为空,任何字符串参数都不能等于String.Empty

而不是我有一个大列表:

if(arg1 == string.Empty || arg1 == null)
{
    throw new ArgumentException("issue with arg1");
}

有没有更快的方法来检查所有的字符串参数?

抱歉,如果我的问题不清楚。

谢谢!

【问题讨论】:

  • 我看了一下,我会将此作为评论发布,因为这并不是真正的答案。在我的书中,如果我们可以定义一个“符号”以用于方法签名中的参数,那就太好了。所以假设我们将非空和非空的检查分配给符号!,然后在方法签名中它可以是 MyMethod(string !myArg),使用 c# 进行自动检查并抛出异常。当然我现在可以用一种方法来做到这一点,但是如果我可以指定一个可以在签名中使用的符号,那么输入起来会快得多!想法?

标签: c# arguments exception


【解决方案1】:

这里真正的问题是你的方法有太多的参数。这使您编写验证代码变得笨拙。也使它在客户端代码上变得笨拙。考虑编写一个辅助类,其中您现在传递的参数是属性。您的方法现在可以只接受一个参数。验证可以在类本身而不是您的方法中完成。

框架中这种模式的典型示例是 Process 类。 ProcessStartInfo 帮助器类使其保持可用。

【讨论】:

    【解决方案2】:

    据我所知,您的问题如何:

    static void Main(string[] args)
    {
        Test(null, "", "", "");
    }
    
    static void Test(MyClass arg1, params string[] args)
    {
        if (args.Count(a => String.IsNullOrEmpty(a)) == args.Length)
        {
            throw new Exception("All params are null or empty");
        }
    }
    

    【讨论】:

    • 你的意思是if (args.Any(a => a == null || (a is string && !string.IsNullOrEmpty(a))){throw new Exception("No param can be null or empty.")}
    • @sr pt:谢谢!关于Any()的优秀提示
    【解决方案3】:

    你可以使用 String.IsNullOrEmpty:

    if (String.IsNullOrEmpty(arg1) )
        throw new ArgumentException("issue with arg1");
    

    如果您使用的是 Framework 4,还有一个 String.IsNullOrWhiteSpace 方法(如果有人使用仅包含空格的字符串调用该方法,您可能还想抛出)。

    您可以创建一个实用方法来检查参数并抛出,但这是您将获得的最短符号。 C# 中没有语法允许您向编译器表达空值是不可接受的,并且让语言为您抛出异常。

    使用框架 4,您还拥有 Code Contracts - 但使用它的语法仍然是方法调用。

    【讨论】:

    • 这很酷,但我想知道是否有更快的方法。在这里大声思考,但如果有某种形式的速记符号可以附加到方法签名中的参数上,这样C# 会在参数为 null 或为空时自动抛出参数异常。
    【解决方案4】:

    有一个很好的库,叫做CuttingEdge.Conditions,它为此提供了一个流畅的界面:

    public void MyMethod(string arg1, string arg2, int arg3, string arg4, MyClass arg5)
    {
        Condition.Requires(arg1, "arg1").IsNotNull().IsNotEmpty().StartsWith("Foo");
    }
    

    它为各种验证提供类型安全条件,包括空值检查、数字范围检查、字符串检查(包括上面的 StartsWith)等...如果您对参数进行多次检查,它可以大大缩短和简化您的验证,最重要的是,使参数检查和异常在整个应用程序中保持一致。

    【讨论】:

    • 不幸的是,它不再维护。我向正在寻找替代方案的人推荐Guard。(免责声明:我是作者)
    【解决方案5】:

    嗯,首先,你可以使用if (!String.IsNullOrEmpty(arg1))来减少if表达式。

    其次,您是否需要在发布版本中检查参数,或者在调试版本中执行参数检查就足够了?这取决于数据的来源。如果此函数由您自己的代码调用并且 args 由您的调用代码处理,则可能仅在调试版本中检查 args 就足够了。在这种情况下,请使用 Debug.Assert(!String.IsNullOrEmpty(arg1), "msg"); 等。断言会从发布版本中删除。

    第三,查看DevLabs: Code Contracts

    【讨论】:

      【解决方案6】:

      您可以创建或使用框架来检查您的方法的合同,例如Code Contracts.

      您还可以创建各种实用方法,例如 ThrowIfNullOrEmpty,它们将封装检查参数的逻辑。

      【讨论】:

        【解决方案7】:
        if (string.IsNullOrEmpty(arg1))
        {
            throw new ArgumentException("issue with arg1");
        }
        

        .NET 4 中还有 code contracts

        【讨论】:

          猜你喜欢
          • 2015-05-08
          • 2016-07-14
          • 2016-01-09
          • 1970-01-01
          • 1970-01-01
          • 2017-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多