可以使用断言作为先决条件



我正在浏览与零处理的处理有关的文章。

推荐之一(根据SO职位)是在nulls无效的情况下使用断言。

我(到目前为止)在测试项目中广泛使用了空。在正常代码(测试项目除外)中使用断言语句对我来说似乎很奇怪。

为什么 ->因为我从未使用过这种方式,所以也从未在任何书中阅读。

问题
1.可以将主张用于先决条件
是否可以2.主张的优点/缺点,而不是检查参数并投掷参数___例外

如果重要的话,我要求.net(不是Java)

您可能想查看代码合同。它们同时提供您的方法的静态检查和运行时检查,您也可以将它们应用于您的界面,以便合同成为您的公共API的一部分。

作为一个例子,从我自己的某些代码中复制(此代码在接口上实现合同):

using System;
using System.Diagnostics.Contracts;
using Project.Contracts.Model.Accounts;
using Project.Contracts.Services;
/// <summary>
/// Data access for accounts.
/// </summary>
[ContractClass(typeof(AccountRepositoryContract))]
public interface IAccountRepository
{
    /// <summary>
    /// Gets the user by id.
    /// </summary>
    /// <param name="userId">The user id.</param>
    /// <returns>The user, or <c>null</c> if user not found.</returns>
    [Pure]
    User GetUserById(int userId);
}
/// <summary>
/// Contract class for <see cref="IAccountRepository"/>.
/// </summary>
[ContractClassFor(typeof(IAccountRepository))]
internal abstract class AccountRepositoryContract : IAccountRepository
{
    /// <summary>
    /// Gets the user by id.
    /// </summary>
    /// <param name="userId">The user id.</param>
    /// <returns>
    /// The user, or <c>null</c> if user not found.
    /// </returns>
    public User GetUserById(int userId)
    {
        Contract.Requires<ArgumentException>(userId > 0);
        return null;
    }
}

一个更简单,更全面的例子:

public class Foo
{
    public String GetStuff(IThing thing)
    {
        // Throws ArgumentNullException if thing == null
        Contract.Requires<ArgumentNullException>(thing != null);
        // Static checking that this method never returns null
        Contract.Ensures(Contract.Result<String>() != null);
        return thing.ToString();
    }
}

这篇文章是关于 Microsoft.VisualStudio.TestTools.UnitTesting.Assert ,而不是 Debug.Assert

我不建议这样做,因为Assert类位于Microsoft.VisualStudio.TestTools.UnitTesting名称空间中,该名称空间是测试内容而不是生产工具。它们也在单独的组件中,您不需要从非测试代码中引用。

ArgumentException(非法参数,用ArgumentNullExceptionArgumentOutOfRangeException进行进一步分割),以及InvalidOperationException(非法状态)进行条件检查。

作为替代方案,也有代码合同。参见史蒂夫的答案。

它们实际上是两个不同的断言。您在单位测试中使用的断言是触发测试故障(当然,它们总是经过测试)。您在其他代码中使用的断言是一个单独的功能(System.Diagnostics.Debug.Assert()),并用作开发过程中的帮助工具,以提醒您如果不满足预期条件。但是,这些断言仅是在调试构建中测试的。如果您制作释放,则断言将无效。因此,它不是一个一般错误处理工具,您不应该计划捕获错误。

仅在测试和开发过程中捕获逻辑错误,告诉您您的假设是否存在。因此,是的,它对于测试前和后条件非常有用。

请注意,这种断言有点有争议,因为它可能会成为您最终使用而不是适当的错误处理的拐杖,并且由于它在发布构建中没有影响,因此您可能会结束使用不存在的错误处理释放软件。(例如,不要使用断言来检查文件是否存在。这是一个真正的错误,实际上可能在现实世界中发生,因此它需要现实世界中的错误处理。)但是,我认为这是一个非常有用的工具,为了测试前后条件,而不必担心性能开销(由于在发行版中删除了测试,因此有效地免费,并且在断言失败时会触发调试器,而不仅仅是抛出例外)

亲自,如果我要在方法中处理nulls,那么我将在上述方法中确定不是而不是使用assert。取而代

本质上,当断言失败时 - 基本上是一个例外。如果要扔ArgumentNullException,我会避免在方法本身中使用尝试捕获来对其进行任何操作,但要在单位测试中处理。

public class A
{
  public double Add(double a, double b)
  {
    if (a == null || b == null)
      throw new ArgumentNullException("");
    return a + b;
  }
}
[TestClass()]
public UnitTest
{
  [TestMethod()]
  public void ATest()
  {
    try
    {
      double d = new A().Add(null, 1);
    }
    catch(ArgumentNullException ex)
    {
      //Fail the test
      Assert.Fail("");
      //Or throw, this will allow you to double click the exception in the unit test and go to the line of code which failed
      throw ex;
    }  
  }
}

相关内容

  • 没有找到相关文章

最新更新