15

Why doesn't #IF Not DEBUG work the way I'd expect in VB.NET?

#If DEBUG Then
   Console.WriteLine("Debug")
#End If

#If Not DEBUG Then
   Console.WriteLine("Not Debug")
#End If

#If DEBUG = False Then
   Console.WriteLine("Not Debug")
#End If
' Outputs: Debug, Not Debug

But, a manually set const does:

#Const D = True
#If D Then
   Console.WriteLine("D")
#End If

#If Not D Then
   Console.WriteLine("Not D")
#End If
' Outputs: D

And, of course, C# has the expected behavior as well:

#if DEBUG
    Console.WriteLine("Debug");
#endif

#if !DEBUG
    Console.WriteLine("Not Debug");
#endif
// Outputs: Debug
Mark Brackett
  • 84,552
  • 17
  • 108
  • 152
  • Works fine for me, the first one displays just Debug in Debug mode and Not Debug, Not Debug in Release mode. Are you sure you don't have something "wierd" going on in your project settings? – Steven Robbins Oct 02 '09 at 19:08
  • Hmmm...I've tried it both with VS2008 in an existing ASP.NET project, and then Snippet Compiler. I'll try a new Console project and see what happens. – Mark Brackett Oct 02 '09 at 19:18
  • It was a new console app I tried. – Steven Robbins Oct 02 '09 at 19:19
  • Argh. A new console app works as expected. Now I'm really confused.... – Mark Brackett Oct 02 '09 at 19:22
  • Odd. Sure someone hasn't messed around with the preprocessor settings for the project? – Steven Robbins Oct 02 '09 at 19:23
  • It's an ASP.NET website project, so it's compiled on demand. Snippet Compiler is also affected...the only thing I can think of is that it's an issue with the Microsoft.VisualBasic.VBCodeProvider (which, AFAIK, both ASP.NET and Snippet Compiler use instead of vbc.exe). Further investigation under way.... – Mark Brackett Oct 02 '09 at 19:37

1 Answers1

10

Turns out, it's not all of VB.NET that's broken - just the CodeDomProvider (which both ASP.NET and Snippet Compiler use).

Given a simple source file:

Imports System
Public Module Module1
    Sub Main()
       #If DEBUG Then
          Console.WriteLine("Debug!")
       #End If

       #If Not DEBUG Then
          Console.WriteLine("Not Debug!")
       #End If
    End Sub
End Module

Compiling with vbc.exe version 9.0.30729.1 (.NET FX 3.5):

> vbc.exe default.vb /out:out.exe
> out.exe
  Not Debug!

That makes sense...I didn't define DEBUG, so it shows "Not Debug!".

> vbc.exe default.vb /out:out.exe /debug:full
> out.exe
  Not Debug!

And, using CodeDomProvider:

Using p = CodeDomProvider.CreateProvider("VisualBasic")
   Dim params As New CompilerParameters() With { _
      .GenerateExecutable = True, _
      .OutputAssembly = "out.exe" _
   }
   p.CompileAssemblyFromFile(params, "Default.vb")
End Using

> out.exe
Not Debug!

Okay, again - that makes sense. I didn't define DEBUG, so it shows "Not Debug". But, what if I include debug symbols?

Using p = CodeDomProvider.CreateProvider("VisualBasic")
   Dim params As New CompilerParameters() With { _
      .IncludeDebugInformation = True, _
      .GenerateExecutable = True, _
      .OutputAssembly = "C:\Users\brackett\Desktop\out.exe" _
   }
   p.CompileAssemblyFromFile(params, "Default.vb")
End Using

> out.exe
Debug!
Not Debug!

Hmm...I didn't define DEBUG, but maybe it defined it for me? But if it did, it must have defined it as "1" - because I can't get that behavior with any other value. ASP.NET, using the CodeDomProvider, must define it the same way.

Looks like the CodeDomProvider is tripping over VB.NET's stupid psuedo-logical operators.

Moral of the story? #If Not is not a good idea for VB.NET.


And now that source is available, I can verify that it does actually set it equal to 1 as I expected:

if (options.IncludeDebugInformation) {
      sb.Append("/D:DEBUG=1 ");
      sb.Append("/debug+ ");
}
Mark Brackett
  • 84,552
  • 17
  • 108
  • 152