我正在浏览与零处理的处理有关的文章。
推荐之一(根据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
(非法参数,用ArgumentNullException
和ArgumentOutOfRangeException
进行进一步分割),以及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;
}
}
}