I\'ve been a professional software engineer for about a year now, having graduated with a CS degree. I\'ve known about assertions for a while in C++ and C, but had no idea t
Use assertions only in cases where you want the check removed for release builds. Remember, your assertions will not fire if you don't compile in debug mode.
Given your check-for-null example, if this is in an internal-only API, I might use an assertion. If it's in a public API, I would definitely use the explicit check and throw.
I don't know how it is in C# and .NET, but in C will assert() only work if compiled with -DDEBUG - the enduser will never see an assert() if it's compiled without. It's for developer only. I use it really often, it's sometimes easier to track bugs.
I've read the answers here and I thought I should add an important distinction. There are two very different ways in which asserts are used. One is as a temporary developer shortcut for "This shouldn't really happen so if it does let me know so I can decide what to do", sort of like a conditional breakpoint, for cases in which your program is able to continue. The other, is a as a way to put assumptions about valid program states in your code.
In the first case, the assertions don't even need to be in the final code. You should use Debug.Assert
during development and you can remove them if/when no longer needed. If you want to leave them or if you forget to remove them no problem, since they won't have any consequence in Release compilations.
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.
Trace.Assert
has the perfect way to achieve this. It won't be removed in production, and can be configured with different listeners using app.config.
So for development the default handler is fine, and for production you can create a simple TraceListener like below which throws an exception and activate it in the production config file.
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) { }
}
And in the production config file:
<system.diagnostics>
<trace>
<listeners>
<remove name="Default"/>
<add name="ExceptionListener" type="Namespace.ExceptionTraceListener,AssemblyName"/>
</listeners>
</trace>
</system.diagnostics>
According to the IDesign Standard, you should
Assert every assumption. On average, every fifth line is an assertion.
using System.Diagnostics;
object GetObject()
{...}
object someObject = GetObject();
Debug.Assert(someObject != null);
As a disclaimer I should mention I have not found it practical to implement this IRL. But this is their standard.
Mostly never in my book. In the vast majority of occasions if you want to check if everything is sane then throw if it isn't.
What I dislike is the fact that it makes a debug build functionally different to a release build. If a debug assert fails but the functionality works in release then how does that make any sense? It's even better when the asserter has long left the company and no-one knows that part of the code. Then you have to kill some of your time exploring the issue to see if it is really a problem or not. If it is a problem then why isn't the person throwing in the first place?
To me this suggests by using Debug.Asserts you're deferring the problem to someone else, deal with the problem yourself. If something is supposed to be the case and it isn't then throw.
I guess there are possibly performance critical scenarios where you want to optimise away your asserts and they're useful there, however I am yet to encounter such a scenario.
Use asserts to check developer assumptions and exceptions to check environmental assumptions.