65.9K
CodeProject 正在变化。 阅读更多。
Home

CuttingEdge.Conditions

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (17投票s)

2008 年 7 月 16 日

MIT

3分钟阅读

viewsIcon

130467

downloadIcon

101

一个基于 .NET 3.5 扩展方法的前置和后置条件验证框架

引言

CuttingEdge.Conditions 是一个库,它帮助开发人员在其 C# 3.0 和 VB.NET 9 代码库中编写前置和后置条件验证。编写这些验证非常简单,并且可以提高代码的可读性和可维护性。

依赖

CuttingEdge.Conditions 是语言无关的,可以与 C# 3.0 和 VB9 一起使用。该库可以在未安装 .NET 3.5 的机器上运行。虽然 CuttingEdge.Conditions.dll 程序集本身依赖于 System.Core (.NET 3.5),但用户可以安全地将其添加到他们的 .NET 2.0 项目中(只要使用 C# 3.0 或 VB9 编译器)。

条件

编写前置条件验证可以提高代码质量。带有验证的代码更容易理解,并允许开发人员更快地发现错误,主要是在开发过程中而不是在调试过程中。然而,编写前置条件验证一直是编程中的弱项。它需要时间来编写,而且我共事过的许多开发人员(即使是我尊敬的那些)都跳过了编写它们。

跳过前置条件验证将导致代码更难使用,并且很可能被滥用。它允许开发人员传递无效的方法参数,这会导致意外的程序行为以及调用堆栈深处的那些可怕的 NullReferenceException。这会导致更多的错误,从而花费更多的时间进行调试。

CuttingEdge.Conditions 库试图降低编写前置条件验证的门槛,并使代码更易读,从而产生更好的代码、更少的错误和更短的开发周期。

为了理解 CuttingEdge.Conditions 如何尝试实现这一点,让我们先看看我们日常可能会写的一些代码。这是一个用传统方式编写前置条件验证的 C# 示例。

void TheOldFashionWay(int id, IEnumerable<int> collection, DayOfWeek day)
{
    if (id < 1)
    {
        throw new ArgumentOutOfRangeException("id", String.Format(
            "id should be greater than 0. The actual value is {0}.", id));
    }
    if (collection == null)
    {
        throw new ArgumentNullException("collection", 
            "collection should not be empty");
    }
    if (collection.Count() == 0)
    {
        throw new ArgumentException("collection should not be empty", 
            "collection");
    }
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Friday)
    {
        throw new InvalidEnumArgumentException(String.Format(
            "day should be between Monday and Friday. " +
            "The actual value is {0}.", day));
    }

    // Do method work
}

对于一些简单的验证来说,这是多么大量的代码!如果采用 CuttingEdge.Conditions,效果看起来是这样的:

void TheConditionsWay(int id, IEnumerable<int> collection, DayOfWeek day)
{
    Condition.Requires(id, "id").IsGreaterThan(0);
    Condition.Requires(collection, "collection").IsNotEmpty();
    Condition.Requires(day, "day").IsInRange(DayOfWeek.Monday, DayOfWeek.Friday);

    // Do method work
} 

这真是截然不同,不是吗?它不仅代码量大大减少,而且非常易读。请注意,这两种方法具有完全相同的契约。两种方法抛出完全相同的异常和异常消息!

除了这些正常的前置条件检查之外,CuttingEdge.Conditions 还支持后置条件检查。与前置条件不同,后置条件的违规纯粹是内部原因。它可以被认为是错误。在这种情况下抛出 ArgumentException 显然会混淆使用该代码的开发人员。由于这种差异,CuttingEdge.Conditions 在后置条件违规时将始终抛出 PostconditionException

这是一个后置条件检查的例子

public ICollection PostconditionExample()
{
    object obj = Activator.CreateInstance(typeof(Collection<int>));

    Condition.Ensures(obj, "obj").IsNotNull().IsOfType(typeof(ICollection));

    return (ICollection)obj;
} 

后置条件示例展示了两个有趣之处。首先,使用 Ensures 扩展方法来启动后置条件验证。其次,方法调用可以以流畅的方式链式调用,如 IsNotNullIsOfType 方法所示。

API

CuttingEdge.Conditions API 提供了许多验证方法,可以轻松覆盖您 99% 的验证需求。目前有 53 种不同检查的 412 个扩展方法。API 可以分为八个组: 

  • 入口点方法
  • 空值检查方法
  • 类型检查方法
  • 比较检查
  • 集合检查
  • 字符串检查
  • 数值检查
  • 评估

方法的数量可能会随着时间的推移而增长,如果您认为有缺失的验证,请在此处、我的博客或 CodePlex 上发表评论。我将考虑将其添加到库中。另外请注意,通过在您自己的项目中放置扩展方法,您可以轻松地用自己的方法扩展 API。有关扩展 CuttingEdge.Conditions 的更多信息,请阅读 CodePlex 上的 Extending CuttingEdge.Conditions wiki

更多信息

CuttingEdge.Conditions 库的第三个稳定版本刚刚发布。您可以从 CodePlex 下载源代码和运行时库。请访问 conditions.codeplex.com我的博客

祝您验证愉快!

© . All rights reserved.