结合代码契约和正则表达式

时间:2011-03-10 17:18:16

标签: c# .net regex code-contracts

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

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
    }
}

非常直截了当。但是,这会抛出一个不可读的异常,另一个说“Member SimpleClass.IsValid的可见性低于封闭方法SimpleClass。#ctor(System.String)”。为什么这是非法的?我应该将正则表达式复制/粘贴到两种方法中吗?这似乎与正确相反。请帮我理解!

3 个答案:

答案 0 :(得分:5)

只需将IsValid标记为public,您就可以了。公共表面合同的所有“组成部分”也必须公开,否则呼叫者无法检查合同是否满意。

  

@ AI-CII我理解这一点,但这也是一个设计漏洞,向消费者揭示实施细节。

  1. 公共方法的合同不是实现细节。一个Contract.Requires说“嘿,我要求我为你做一些工作。”如果呼叫者看不到“this”,呼叫者如何验证合同是否满足?

  2. 您没有公开方法IsValid的实现细节,只是暴露了被调用者必须满足的工作。

答案 1 :(得分:5)

另一种方法是避免“原始的痴迷”,并使用适合您目的的类别,例如:

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

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

答案 2 :(得分:1)

正如Jason已经说过的那样,Code Contracts要求该方法是公开的,因为您已经通过异常消息自己想出了自己。

但我明白,仅仅公开它并不合适。也许正则表达式条件可以封装到辅助类的静态全局函数中?

E.g。如果要检查字符串是否是有效的URL。

UrlHelper.IsValidUrl( string url )

这让我感兴趣所以我开始做一些谷歌搜索。有一个解决方案!虽然我仍然更喜欢使用静态方法的辅助类。

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