【问题标题】:Combining code contracts and regex结合代码合同和正则表达式
【发布时间】:2011-03-10 17:18:15
【问题描述】:

所以我有一个非常简单的类,其中一个字符串作为属性。这个字符串必须有一定的模式。我正在尝试使用代码合同来执行此操作。这个类看起来像这样:

class SimpleClass
{
    public Property { get; set; }

    public SimpleClass(string prop)
    {
      Contract.Requires(IsValid(prop));
      this.Property = prop;
    }

    [ContractInvariantMethod]
    void ObjectInvariant()
    {
      Contract.Invariant(IsValid(Property));
    }

    bool IsValid(string arg)
    {
      // Use regex to check if arg is a valid string
    }
}

非常简单。但是,这会引发一个不可读的异常,并且另一个说“成员 SimpleClass.IsValid 的可见性低于封闭方法 SimpleClass.#ctor(System.String)”。为什么这是非法的?我应该将正则表达式复制/粘贴到这两种方法中吗?这似乎与权利相反。请帮我理解!

【问题讨论】:

  • 我认为您必须使用IsValid 方法public 才能检查string
  • @AI-CII 我理解,但这也是一个设计缺陷,将实现细节暴露给消费者。
  • 你确定不能删除第一个Contract.Requires

标签: c# .net regex code-contracts


【解决方案1】:

另一种方法是避免“原始痴迷”并使用为您的目的量身定制的课程,例如:

public SimpleClass(Email address)
{
    // no need to check, it must be valid :)
}

... 然后将所有验证逻辑封装在 Email 类中。您仍然会遇到关于验证的“字符串格式”问题,但我认为更好的习惯用法是创建一个名为 Email.TryParse 的方法,并按照 int.TryParse 的方式对其进行调整。

【讨论】:

  • 我想过这个,我认为这是最清晰的做事方式。谢谢!
【解决方案2】:

只需将IsValid 标记为public 即可。公共表面契约的所有“组件”也必须是公共的,否则调用者无法检查契约是否得到满足。

@AI-CII 我明白这一点,但这也是一个设计缺陷,将实现细节暴露给消费者。

  1. 公共方法的契约不是实现细节。 Contract.Requires 说:“嘿,我要求这是真的,我才能为你做一些工作。”如果调用者看不到“this”,调用者如何验证合约是否满足?

  2. 您没有公开方法 IsValid 的实现细节,您只是公开了被调用者完成其工作所必须满足的内容。

【讨论】:

  • 在我的实际代码中,该属性显然不称为属性,想象一下它就像电子邮件地址。调用者应该知道它的外观。我只强制执行它以防止细微的错误。 IsValid 方法是一个实现细节,因为它公开了我如何检查有效内容,而不是我实际检查的内容。我赞成“公共方法的合同不是实现细节”,因为我以前没有这样想过。
【解决方案3】:

正如 Jason 已经说过的,代码合同要求方法是公开的,因为您已经通过异常消息弄清楚了。

不过,我理解只是将其公开是不对的。也许正则表达式条件可以封装到辅助类的静态全局函数中?

例如如果要检查一个字符串是否是一个有效的 URL。

UrlHelper.IsValidUrl( string url )

这让我很感兴趣,所以我开始用谷歌搜索。有解决办法!虽然我仍然希望尽可能使用带有静态方法的辅助类。

它被称为Code Contract Abbreviators。但是,您需要自己将源文件包含到您的项目中。

【讨论】:

猜你喜欢
  • 2012-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
  • 1970-01-01
  • 1970-01-01
  • 2015-01-14
  • 2018-07-04
相关资源
最近更新 更多