到目前为止,我已经做了一年的专业软件工程师,并获得了计算机科学学位。我知道c++和C中的断言有一段时间了,但直到最近才知道它们存在于c#和。net中。

我们的生产代码不包含任何断言,我的问题是这个…

我应该开始在我们的生产代码中使用断言吗?如果可以,什么时候使用它最合适?这样做会更有意义吗

Debug.Assert(val != null, "message");

or

if ( val == null )
    throw new exception("message");

当前回答

我已经在这里阅读了答案,我认为我应该添加一个重要的区别。使用断言有两种非常不同的方式。一种是作为临时的开发人员快捷方式,表示“这不应该真的发生,所以如果它发生了,就告诉我,这样我就可以决定怎么做”,有点像一个条件断点,用于你的程序能够继续的情况。另一种方法是在代码中假设有效的程序状态。

在第一种情况下,断言甚至不需要出现在最终代码中。您应该使用Debug。在开发期间断言,如果/当不再需要时,您可以删除它们。如果你想要保留它们或者忘记删除它们,没有问题,因为它们在发布汇编中不会有任何后果。

But in the second case, the assertions are part of the code. They, well, assert, that your assumptions are true, and also document them. In that case, you really want to leave them in the code. If the program is in an invalid state it should not be allowed to continue. If you couldn't afford the performance hit you wouldn't be using C#. On one hand it might be useful to be able to attach a debugger if it happens. On the other, you don't want the stack trace popping up on your users and perhaps more important you don't want them to be able to ignore it. Besides, if it's in a service it will always be ignored. Therefore in production the correct behavior would be to throw an Exception, and use the normal exception handling of your program, which might show the user a nice message and log the details.

跟踪。Assert有实现这一点的完美方法。它不会在生产环境中被删除,并且可以使用app.config配置不同的侦听器。 因此,对于开发来说,默认的处理程序就可以了,对于生产来说,您可以创建一个简单的TraceListener(如下所示),它会抛出一个异常并在生产配置文件中激活它。

using System.Diagnostics;

public class ExceptionTraceListener : DefaultTraceListener
{
    [DebuggerStepThrough]
    public override void Fail(string message, string detailMessage)
    {
        throw new AssertException(message);
    }
}

public class AssertException : Exception
{
    public AssertException(string message) : base(message) { }
}

在产品配置文件中:

<system.diagnostics>
  <trace>
    <listeners>
      <remove name="Default"/>
      <add name="ExceptionListener" type="Namespace.ExceptionTraceListener,AssemblyName"/>
    </listeners>
  </trace>
 </system.diagnostics>

其他回答

仅在希望为发布版本删除检查的情况下使用断言。请记住,如果不在调试模式下编译,断言将不会触发。

对于检查为空的示例,如果这是在仅限内部的API中,我可能会使用断言。如果它在一个公共API中,我肯定会使用显式检查和抛出。

我不知道它在c#和。net中是怎样的,但在C中assert()只在使用- ddebug编译时工作-如果没有编译,最终用户将永远不会看到assert()。仅供开发人员使用。我经常使用它,它有时更容易跟踪错误。

使用断言检查开发人员的假设,使用异常检查环境的假设。

摘自《实用程序员:从熟练工到高手》

Leave Assertions Turned On There is a common misunderstanding about assertions, promulgated by the people who write compilers and language environments. It goes something like this: Assertions add some overhead to code. Because they check for things that should never happen, they'll get triggered only by a bug in the code. Once the code has been tested and shipped, they are no longer needed, and should be turned off to make the code run faster. Assertions are a debugging facility. There are two patently wrong assumptions here. First, they assume that testing finds all the bugs. In reality, for any complex program you are unlikely to test even a miniscule percentage of the permutations your code will be put through (see Ruthless Testing). Second, the optimists are forgetting that your program runs in a dangerous world. During testing, rats probably won't gnaw through a communications cable, someone playing a game won't exhaust memory, and log files won't fill the hard drive. These things might happen when your program runs in a production environment. Your first line of defense is checking for any possible error, and your second is using assertions to try to detect those you've missed. Turning off assertions when you deliver a program to production is like crossing a high wire without a net because you once made it across in practice. There's dramatic value, but it's hard to get life insurance. Even if you do have performance issues, turn off only those assertions that really hit you.

如果我是你,我会这样做:

Debug.Assert(val != null);
if ( val == null )
    throw new exception();

或者避免重复条件检查

if ( val == null )
{
    Debug.Assert(false,"breakpoint if val== null");
    throw new exception();
}