#define, #if, #elif, #error, # warning RRS feed

  • Question

  • Hi everyone,
    I have some doubts about #define, #if, #elif, #error, # warning.
    Are are any real advantages of using these in C# programming language ?

    Friday, June 9, 2006 1:16 PM

All replies

  • It doesn't happen often, but there are situations where conditional compilation comes in handy with C#.  Just the other day I was writing some code that used ODBC that had to be compilable with .NET 1.0 and .NET 1.1.  Since ODBC moved from the Microsoft.Data.Odbc to the System.Data.Odbc namespace between those two versions, I used #if to include the correct namespace in each file that used ODBC.  I have another program where there are several debug switches that can be turned on/off that were implemented with #if.  I could have just used runtime if statements, but the extra checks would have slowed down critical pieces of code.  That said, I've only used those pragmas twice in the 4 years since I started writing C#, so its not something you see every day.
    Friday, June 9, 2006 2:28 PM
  • Just a note, instead of using #define DEBUG I found out about this: [Conditional("DEBUG")]. It is placed before a function and the compiler will ignore this function call when not in debug.
    Friday, June 9, 2006 2:35 PM
  • Are there any other opinions about this thread ??
    Friday, June 9, 2006 3:33 PM
  • As Nimrand said the only purpose #if and #elif serve is to conditionally compile that can not be otherwise specified (such as between versions of .NET).  As ThE_lOtUs mentioned .NET supports the ConditionalAttribute attribute that lets you conditionally include types and members based on compile-time definitions.  Unlike #if/#define in C++ these types/members are still compiled into the assembly but their usage is conditionally specified when other assemblies link to them.  For example the Debug class uses this attribute to cause the runtime to skip over it when running release builds.  Some people also use this attribute for conditionally including test code.  For example you could add a bunch of methods to your classes that expose internal details for use in automated testing but due to conditional attributes you can prevent normal use of the methods. 

    The problem with ConditionalAttribute is that it is an all or nothing affair.  For example you can't specify a condition where it is a debug build or you are compiling for testing purposes.  You can specify multiple conditional attributes but I believe they are effectively ANDed together (might be ORed but you'll still have a problem).  Therefore #if/#elif also comes in useful here.  Finally note that the attribute requires that the symbol be defined at some point.  This definition can come from the command-line option to the compiler, a project setting or through the #define keyword.

    As for #warning and #error they could be useful in the situations where you want to warn someone about the usage of a feature.  The ObsoleteAttribute is used to mark functionality as obsolete so this attribute is normally used but again there might be circumstances where it won't work.  For example I use to have a simple dialog class that displayed the standard "Not Implemented" message.  I used this dialog in UI code where the functionality wasn't done yet.  Using ConditionalAttribute I had two versions of the ShowDialog method.  In debug builds the method simply showed a message box.  In official release builds however I used the #error to indicate that I was trying to build a release that contained unimplemented functionality.  It's the only time I found the functionality useful but there are probably a few others.

    All in all I have not had to use any of the preprocessor tokens since I started writing C# code years ago.  Unlike C++ they just aren't as important given the relative power of ConditionalAttribute.

    Michael Taylor - 6/9/06

    Friday, June 9, 2006 8:08 PM
  • Hi,

    First of all,thanks very much foryour explantory reply.

    I think we can do these kind of things such that conditionally compiling by not using these keyowrds, is not it?

    For instance, we can define two same method in a normal (if and else)condition, cannot we ?

    So, ı heard that these keywords are compiled before the normal codes, is it correct ?







    Saturday, June 10, 2006 6:42 AM
  • I'm not sure I follow what you're asking here but there are some things that can't be done with #if.  In general anything that can't or shouldn't compile must be enclosed with #if.  For example suppose you are the writer of a class library and your clients want use both v1.x and v2.0 of .NET.  If you want to represent a collection of objects in your library you can either go the v1.x route or the v2.0 route with generics.  In order to ensure that your code continues to compile under either version (so you can have one code base) you must either limit yourself to the features available in v1.x only or you must use #if to conditionally compile in v2.0 features.  When compiled (and used) under v1.x your library would provide a collection of objects.  Under v2.0 your library would provide a strongly-typed collection of objects.  Without #if you can not compile your code against v1.x.  It simply won't work.  You could argue that you would keep the implementations separate such that you had separate projects (one for v1.x and one for v2.0) but now you have made it more difficult to add new classes later because you have to maintain multiple project files. 

    Another example that was common in C++ but still relevant in C# is when you want to write code that is somewhat independent of an underlying type.  The defacto example is strings in Windows.  If you compile with ANSI then strings are characters.  If you compile with Unicode then strings are wide characters.  We don't have this specific problem in .NET but there are quite possibly cases similar to this that might occur. 

    I'm not saying that you should use #if in every project.  My point is that the functionality is there if you need it and there are some cases where it is the only option.  I have only needed to use #if in one situation since I started coding in .NET years ago so I don't consider the need for such functionality to be as important or common as it was in C++ but the need is still there.  Ultimately if you don't like or feel comfortable with the feature then don't feel obligated to use it.  As an aside it was probably added more to be complete than anything because most languages support this conditional compilation option in some form or fashion.

    As for when it is handled C# doesn't use a preprocessor as many other languages do.  However it does process the #symbol tokens first.  I'd say the scanner probably runs through the source file and picks out and applies the directives before it starts processing the actual source file but it is possible that it does it inline as it comes to the tokens.  You'd have to look at the compiler code to know for sure.  Nevertheless you can consider the preprocessor tokens to be stripped out and applied prior to compilation.

    Michael Taylor - 6/10/06

    Saturday, June 10, 2006 10:39 PM

  • Thanks for your really explanatory reply but if anyone please send some formatted codes about these preprocessors, I will be more happy.

    Tuesday, June 13, 2006 12:34 PM