【问题标题】:.Net 3.5 Implementation of String.IsNullOrWhitespace with Code Contracts.Net 3.5 使用代码契约实现 String.IsNullOrWhitespace
【发布时间】:2011-06-19 09:46:30
【问题描述】:

我正在尝试在我的 .Net 3.5 (C#) 项目中使用合同。我发现我在方法的开头写了类似if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(s.Trim())) throw new ArgumentException("Required", "s"); 的东西。

我可以将它们保留在那里并使用旧合同。我可以将其更改为Contract.Requires(s!= null && string.IsNullOrEmpty(s.Trim()));。但是除了不太确定条件的 Whitespace 部分的正确性或性能之外,这些都是蹩脚的(意见)。

相反,我尝试将条件封装在合同中使用的方法中。问题是我仍然无法弄清楚如何以声明方式描述 Whitespace 部分。静态检查器会根据我的编写方式发现几个问题。

我想听听 cmets 关于数据内容检查的适当性,例如这个对于空格以及正确定义的检查。

public static class str
{
    [Pure]
    public static bool IsNullOrWhitespace(string s)
    {
      Contract.Ensures(s != null || Contract.Result<bool>());
      Contract.Ensures((s != null && !Contract.ForAll<char>(s, c => char.IsWhiteSpace(c))) || Contract.Result<bool>());

      if (s == null) return true;

      for (var i = 0; i < s.Length; i++)
      {
        if (!char.IsWhiteSpace(s, i))
        {
          Contract.Assume(!Contract.ForAll<char>(s, c => char.IsWhiteSpace(c)));
          return false;
        }
      }


      return true;
    }
}

这可能有点草率,但我最初的实验方法就在这里。 a、b 和 c 上的断言失败或未经证实。

static void Test()
{
  string a = null;
  string b = "";
  string c = "     ";
  string d = "xyz";
  string e = "  xyz  ";

  if (!str.IsNullOrWhitespace(a))
  {
    Contract.Assert(a != null);
    a = a.Trim();
  }

  if (!str.IsNullOrWhitespace(b))
  {
    Contract.Assert(b != null && b != "");
    b = b.Trim();
  }

  if (!str.IsNullOrWhitespace(c))
  {
    Contract.Assert(c != null && c != "     ");
    c = c.Trim();
  }

  if (!str.IsNullOrWhitespace(d))
  {
    d = d.Trim();
  }

  if (!str.IsNullOrWhitespace(e))
  {
    e = e.Trim();
  }
}

【问题讨论】:

  • 这是一个你使用 3.5 的虫子。 .NET 4.0 中有一个方法叫做 IsNullOrWhitespace...
  • @Alastair Pitts:OP 已经清楚地知道这一点。因此标题。
  • 当然,我就是从那里得到它的。 4.0 版本是否为它正确定义了代码协定?

标签: c# code-contracts conditional-statements


【解决方案1】:

这是 .NET 4 的内置合同:

Contract.Ensures(
    (Contract.Result<bool>() && ((str == null) || (str.Length == 0)))
    ? ((bool) true)
    : ((Contract.Result<bool>() || (str == null))
      ? ((bool) false)
      : ((bool) (str.Length > 0)))

, null, "Contract.Result<bool>() && (str == null || str.Length == 0) ||\r\n!Contract.Result<bool>() && str != null && str.Length > 0");

尽管它很复杂,但您可以看到没有提到空格。我已经尝试了好几次,但我无法让静态检查器满意。

似乎有几个问题阻止我编写它,所以我在代码合同论坛上提出了一些问题。

我的合同是:

Contract.Ensures(Contract.Result<bool>() ==
                 (s == null || Contract.Exists(s, char.IsWhiteSpace)))

【讨论】:

  • 来自Jack Leitch's answer to a similar question: > Code Contracts User Manual 声明,“静态合约检查器尚未处理量词 ForAll 或 Exists。”真的。是的。
  • @uosɐſ: 好久没更新了。它确实可以处理 Forall/Exists,但还不能处理所有情况。
  • Porges - 案件必须有多简单?既然您似乎对此很了解,那么您是 Code Contracts 团队的成员还是只是一个狂热的追随者?
  • 我只是喜欢他们要去的地方 :) 我已经让它适用于几个案例(主要是非空的东西),但匿名函数似乎存在一些问题(/method组)目前,我认为这是干扰这里。
猜你喜欢
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多