I have this program here:
namespace TodoPlus {
using System.Diagnostics;
public class LameProg {
public LameProg() {}
public static void Main(string[] args) {
int a = 2;
int b = 3;
Debug.Assert(a == b, "Bleh");
System.Console.WriteLine("Haha it didn't work");
}
}
}
And somehow, Debug.Assert is not working.
I am using Mono 2.10.5 and this is what I use to compile and execute:
$ dmcs LameProg.cs
$ mono ./LameProg.exe
How can I make this work? I wish it to have the same affect as the assert macro in C, which is to say it should just downright crash the program. Is it possible to do this with Debug.Assert or is there some other function that achieves this?
Thanks.
Debug.Assert is annotated with [ConditionalAttribute("DEBUG")]. This means that all invocations are removed by the compiler unless the DEBUG preprocessor symbol is defined. Try this:
$ dmcs -d:DEBUG LameProg.cs
Mono does not show a dialog box like Microsoft's .NET implementation when an assertion is hit. You need to set a TraceListener, e.g.
$ export MONO_TRACE_LISTENER=Console.Error
$ mono LameProg.exe
Debug.Assert invocations are typically used in debug builds and removed from release builds. If you want to make sure that a certain condition holds, and this check should be present in release builds, use an if
statement and throw
an exception:
public static void Main(string[] args)
{
int a = 2;
int b = 3;
if (a != b)
{
throw new Exception("Bleh");
}
System.Console.WriteLine("Haha it didn't work");
}
There's another trick: you can add "exit now" behavior through a TraceListener, because Debug.Assert failures trigger a call to Fail() in the trace listener.
You still need to -define:DEBUG (and TRACE?). I personally expect Assert() calls (in DEBUG builds) to stop my program, dump debug info and exit. So, this is how I do it:
In my code I install a custom trace listener to dump stack and add a call to Exit(). And viola! You have an industry standard response to Assert.Fail(). You could also, for example, print timestamps here, etc.
public class DumpStackTraceListener : TraceListener
{
public override void Write( string message )
{
Console.Write( message );
}
public override void WriteLine(string message)
{
Console.WriteLine( message );
}
public override void Fail(string message)
{
Fail( message, String.Empty );
}
public override void Fail(string message1, string message2)
{
if (null == message2)
message2 = String.Empty;
Console.WriteLine( "{0}: {1}", message1, message2 );
Console.WriteLine( "Stack Trace:" );
StackTrace trace = new StackTrace( true );
foreach (StackFrame frame in trace.GetFrames())
{
MethodBase frameClass = frame.GetMethod();
Console.WriteLine( " {2}.{3} {0}:{1}",
frame.GetFileName(),
frame.GetFileLineNumber(),
frameClass.DeclaringType,
frameClass.Name );
}
#if DEBUG
Console.WriteLine( "Exiting because Fail" );
Environment.Exit( 1 );
#endif
}
}
Combine with a call to:
#if DEBUG
Debug.Listeners.Add( new DumpStackTraceListener() );
#endif
And you're good to go.
I believe you need two things: the DEBUG attribute to the compiler, and a 'trace listener' for the runtime. I got it to work with
% export MONO_TRACE_LISTENER=Console.Error
% mcs -define:DEBUG -debug Prog.cs
% mono Prog.exe
That still doesn't exit immediately on assertion failure as I would have expected, but at least it prints something.