在方法开头没有一堆if的情况下,将输入参数强制执行到方法中?

时间:2008-12-11 19:08:33

标签: c# .net

我想知道在我的方法中是否有一种不那么详细的输入验证方法。例如,我通常写这样的东西:

public string SomeFunction(string param1, int param2)
{
    if(string.IsNullOrEmpty(param1)){
        throw new ArgumentException("bla", "param1");
    }
    if(param2 < 0 || param2 > 100 || param2 == 53)
    {
         throw new ArgumentOutOfRangeException("eek", "param2");
    }
}

现在,我想知道是否有办法设置参数约束并让编译器已经为我处理了这些?我相信这被称为“契约”,我记得看到Spec#应该这样做,但这似乎是一个实验研究项目。

所以我想知道:对于.net 3.5 SP1和理想情况下.net 3.0的输入参数,有没有什么可以给出一个干净的约束条件(至少是像string.IsNullOrEmpty那样经常重复的那些)?

7 个答案:

答案 0 :(得分:6)

嗯,你可以用AOP做点什么,看看PostSharp

这可以用来注入必要的代码,但它会给编译步骤和编译代码增加一些开销。

代码合同也将包含在.NET 4.0中,请阅读有关此here的更多信息。

答案 1 :(得分:2)

您可以引入CheckParameter方法,这样您的原始方法中只有一行代码。

这样的事情:

public string SomeFunction(string param1, int param2)
{
    CheckParameterNotNull(param1);
    CheckParameterRange(param2, 0, 100, 53); 
...
}

当然,您需要一些智能的CheckParameter方法来适应您的所有情况。

答案 2 :(得分:2)

三个字:design by contract

可以在此处找到C#的一个实现:http://www.codeproject.com/KB/cs/designbycontract.aspx

答案 3 :(得分:1)

考虑Microsoft Research的“Spec#”:http://research.microsoft.com/SpecSharp/

它扩展了C#以允许您定义合同,并且他们已经投入了大量的工作来将合同纳入BCL和东西。

答案 4 :(得分:0)

在WebForms类型世界之后进行建模,您可以使用一组ErrorProvider控件并将它们附加到您所关注的关键TextBoxes,CheckBoxes等。无论何时用户更改焦点,您都可以在这些字段中启动检查,或者不管您多喜欢这样做。

然后,您可以创建一个名为IsFormValid的方法,该方法将检查所有ErrorProviders,并在所有ErrorProviders签出时返回一个简单的True值。

然后在你所有的主要代码中,你所要做的就是包装你的处理......

if (IsFormValid)
{
   // Processing Magic Goes here.
}

这样做的好处是你可能会有不同的“有效”状态,具体取决于特定方法试图完成的内容。确定电话号码字段可能无效并显示一个小红点,但这不应阻止UpdateFirstLastName方法启动。

答案 5 :(得分:0)

与此同时,自提出这个问题以来,代码合约已经发展,看起来像银弹。

当前的CTP是available here(对于.net 3.5),它是.net 4.0的一部分。

答案 6 :(得分:0)

您可以按原样保留所有参数检查代码,但随后将实际工作委托给私有函数。私有函数不会进行参数检查,因为它只会被公共网守功能调用。

private string InternalSomeFunction(string param1, int param2)
{
  /* implementation goes here */
}

public string SomeFunction(string param1, int param2)
{
  if (string.IsNullOrEmpty(param1)) {
    throw new ArgumentException("bla", "param1");
  }
  if (param2 < 0 || param2 > 100 || param2 == 53) {
    throw new ArgumentOutOfRangeException("eek", "param2");
  }
  return InternalSomeFunction(param1, param2);
}

它和原作一样冗长,但至少你的主要功能并不是那些对方法实现并不重要的东西。

另一方面,通过将参数检查代码从实现的其余部分移开,这也消除了检查的一些自我记录方面。例如,当您查看InternalSomeMethod时,不再提醒param1将始终是有效的非空字符串,因此您或维护程序员可能会想要添加一个检查对于后来的内部方法。

免费获取贴纸的机会↓↓↓
豫ICP备18024241号-1