How do you use #define? - c#

I'm wondering about instances when it makes sent to use #define and #if statements. I've known about it for a while, but never incorporated it into my way of coding. How exactly does this affect the compilation?
Is #define the only thing that determines if the code is included when compiled? If I have #define DEBUGme as a custom symbol, the only way to exclude it from compile is to remove this #define statement?

In C# #define macros, like some of Bernard's examples, are not allowed. The only common use of #define/#ifs in C# is for adding optional debug only code. For example:
static void Main(string[] args)
{
#if DEBUG
//this only compiles if in DEBUG
Console.WriteLine("DEBUG")
#endif
#if !DEBUG
//this only compiles if not in DEBUG
Console.WriteLine("RELEASE")
#endif
//This always compiles
Console.ReadLine()
}

#define is used to define compile-time constants that you can use with #if to include or exclude bits of code.
#define USEFOREACH
#if USEFOREACH
foreach(var item in items)
{
#else
for(int i=0; i < items.Length; ++i)
{ var item = items[i]; //take item
#endif
doSomethingWithItem(item);
}

Is #define the only thing that
determines if the code is included
when compiled? If I have #define
DEBUGme as a custom symbol, the only
way to exclude it from compile is to
remove this #define statement?
You can undefine symbols as well
#if defined(DEBUG)
#undef DEBUG
#endif

Well, defines are used often for compile time constants and macros. This can make your code a bit faster as there are really no function calls, the output values of the macros are determined at compile time. The #if's are very useful. The most simple example that I can think of is checking for a debug build to add in some extra logging or messaging, maybe even some debugging functions. You can also check different environment variables this way.
Others with more C/C++ experience can add more I am sure.

I often find myself defining some things that are done repetitively in certain functions. That makes the code much shorter and thus allows a better overview.
But as always, try to find a good measure to not create a new language out of it. Might be a little hard to read for the occasional maintenance later on.

It's for conditional compilation, so you can include or remove bits of code based upon project attributes which tend to be:
Intended platform (Windows/Linux/XB360/PS3/Iphone.... etc)
Release or Debug (Generally logging, asserts etc are only included in a debug build)
They can also be used to disable large parts of a system quickly,
for example, during development of a game, I might define
#define PLAYSOUNDS
and then wrap the final call to play a sound in:
#ifdef PLAYSOUNDS
// Do lots of funk to play a sound
return true;
#else
return true;
So it's very easy for me to turn on and off the playing of sounds for a build. (Typically I don't play sounds when debugging because it gets in the way of my personal music :) )
The benefit is that you're not introducing a branch through adding an if statement....

#Ed: When using C++, there is rarely any benefit for using #define over inline functions when creating macros. The idea of "greater speed" is a misconception. With inline functions you get the same speed, but you also get type safey, and no side-effects of preprocessor "pasting" due to the fact that parameters are evaluated before the function is called (for an example, try writing the ubiquitous MAX macro, and call it like this: MAX(x++, y).. you'll see what I'm getting at).
I have never had to use #define in my C#, and I very rarely use it for anything other that platform and compiler version checking for conditional compilation in C++.

Perhaps the most common usees of #define in C# is to differentiate between debug/release and different platforms (for example Windows and X-Box 360 in the XNA framework).

Related

Selectively remove preprocessor directives using Roslyn

I want to use Roslyn to clean the code of some of the older preprocessor directives.
For example, from this code
#define TEST_1_0
#define TEST_1_1
namespace ConsoleApplication1
{
class TypeName
{
public static void Main(string[] args)
{
#if TEST_1_0
int TEST_1_0 = 1;
#if TEST_1_1
int TEST_1_1 = 1;
#else//TEST_1_1
int TEST_1_1 = 0;
#endif//TEST_1_1
#else//TEST_1_0
int TEST_1_0 = 0;
#endif//TEST_1_0
}
}
}
I'd like to remove else//TEST_1_0, but keep the else//TEST_1_1. I cannot count on the comments, so I should related a #if with its corresponding #else, if there is one.
Finding the #if is easy, but finding the corresponding #else is less easy.
I tried two strategies:
Here i lookup #else//TEST_1_0 in the analyzer, and create a codefix for that location
Here I just create a codefix for #if TEST_1_0 in analyzer, and try to get to the corresponding else from the CodeFixprovider
Both get quite complicated quickly, it seems problematic that directives are trivia, which are spread out over the leadingTrivia of different SyntaxTokens. Changes in the code affect the location directives around quite a bit so it looks like lots of work to program all cases..
Am I missing something? Is there an easier way to do this without programming all the different cases by hand?
Would you go for strategy 1 or 2?
I agree with Arjan - Roslyn in not usable for the task. To solve a similar task I made my own simple C# preprocessor tool based on regexp and Python sympy library: undefine. I believe it would be helpful for you. As for the task you described, try the following command:
>> python undefine apply -d TEST_1_0 YourFile.cs
I concluded that roslyn is not the way to go here.
Roslyn models preprocesessor directives as trivia in the syntax tree, and the location of trivia has great variation depending on the structure of the actual code.
Therefore working on the syntax tree introduces lookup complexities that are not an issue when working text based, and more complexity means more RISK. Binaries should be the same before/after processing!
So I chose to abandon Roslyn and simply parse the code/directive mix as text, using regex to parse and the good-old stack to handle the directive logic.
Now it's much easier, even a piece of cake ..
Still need to handle some encoding issues, then I'm done! :)
Happy parsing!

how to add debug code? (should go to Debug, shouldn't go to Release)

I need to log a lot of information in my software for debugging.
However I need this option only during development, I would prefer to exclude all this code in Release.
Of course I can surround the place I want to debug with "if":
if (isDebugMode()) {
Logger.log(blahblah);
}
But because my software is pretty time-critical, I want to avoid a lot of unnesseray "if" tests.
I.e. I think I need analog of c "#define #ifdef #ifndef". Are there any technics in c# or .net to solve my task easily?
You can use [ConditionalAttribute("DEBUG")] in front of your Logger.log method so it will only get compiled in debug mode and completely removed in release mode.
This is how the Debug class methods are all marked.
The upside of this compared to using the #if approach is that code with the Conditional attribute doesn't even exist at runtime, and all references to it get removed, instead of staying there with an empty body (or however you'd compile it conditionally).
Why don't you instead use the DEBUG symbol?
#if DEBUG
// debug only code here
#endif
Here is an article describing all of the preprocessor directives available to you in C#, and you are also able to define your own preprocessor variables in your project's properties menu.
As others have mentioned, you can use a combination of the "preprocessor" directives:
#if DEBUG
ThisWholeSectionIsTreatedAsACommentIfDEBUGIsNotDefined();
#endif
and the conditional attribute:
Debug.Assert(x); // Call will be removed entirely in non-debug build because it has conditional attr
However, it is important to realize that one of them is a part of the lexical analysis of the program and the other is part of the semantic analysis. It is easy to get confused. My article on the difference might help:
http://ericlippert.com/2009/09/10/whats-the-difference-between-conditional-compilation-and-the-conditional-attribute/
You can use this as a native alternative for debug only logging:
Debug.Write("blah blah");
which will only be logged if this is a debug build.
Conditional attribute could help in this case.
Something like this:
class DebugModeLogger
{
[Conditional("DEBUG")]
public static void WriteLog(string message)
{
//Log it
}
}
Extract from MSDN:
The attribute Conditional enables the definition of conditional methods. The Conditional attribute indicates a condition by testing a conditional compilation symbol. Calls to a conditional method are either included or omitted depending on whether this symbol is defined at the point of the call. If the symbol is defined, the call is included; otherwise, the call (including evaluation of the parameters of the call) is omitted.

Where do Label_ markers come from in Reflector and how to decipher them?

I'm trying to understand a method using the disassembly feature of Reflector. As anyone that's used this tool will know, certain code is displayed with C# labels that were (presumably) not used in the original source.
In the 110 line method I'm looking at there are 11 label statements. Random snippet examples:
Label_0076:
if (enumerator.MoveNext())
{
goto Label_008F;
}
if (!base.IsValid)
{
return;
}
goto Label_0219;
Label_0087:
num = 0;
goto Label_01CB;
Label_01CB:
if (num < entityArray.Length)
{
goto Label_0194;
}
goto Label_01AE;
Label_01F3:
num++;
goto Label_01CB;
What sort of code makes Reflector display these labels everywhere and why can't it disassemble them?
Is there a good technique for deciphering them?
Actually, the C# compiler doesn't do much of any optimization - it leaves that to the JIT compiler (or ngen). As such, the IL it generates is pretty consistent and predictable, which is why tools like Reflector are able to decompile IL so effectively. One situation where the compiler does transform your code is in an iterator method. The method you're looking at probably contained something along the lines of:
foreach(var x in something)
if(x.IsValid)
yield return x;
Since the iterator transformation can be pretty complex, Reflector can't really deal with it. To get familiar with what to look for, write your own iterator methods and run them through Reflector to see what kind of IL gets generated based on your C# code. Then you'll know what to look for.
You're looking at code generated by the compiler. The compiler doesn't respect you. No, really. It doesn't respect me or anybody else, either. It looks at our code, scoffs at us, and rewrites it to run as efficiently as possible.
Nested if statements, recursion, "yield"s, case statements, and other code shortcuts will result in weird looking code. And if you're using lambdas with lots of enclosures, well, don't expect it to be pretty.
Any where, any chance the compiler can rewrite your code to make it run faster it will. So there isn't any one "sort of code" that will cause this. Reflector does its best to disassemble, but it can't divine the author's original code from its rewritten version. It does its best (which sometimes is even incorrect!) to translate IL into some form of acceptable code.
If you're having a hard time deciphering it, you could manually edit the code to inline goto's that only get called once and refactor goto's that are called more than once into method calls. Another alternative is to disassemble into another language. The code that translates IL into higher level languages isn't the same. The C++/CLI decompiler may do a better job for you and still be similar enough (find/replace -> with .) to be understandable.
There really isn't a silver bullet for this; at least not until somebody writes a better disassembler plugin.

Is there a way to get VS2008 to stop warning me about unreachable code?

I have a few config options in my application along the lines of
const bool ExecuteThis=true;
const bool ExecuteThat=false;
and then code that uses it like
if(ExecuteThis){ DoThis(); }
if(ExecuteThat){ DoThat(); } //unreachable code warning here
The thing is, we may make slightly different releases and not ExecuteThis or ExecuteThat and we want to be able to use consts so that we don't have any speed penalties from such things at run time. But I am tired of seeing warnings about unreachable code. I'm a person that likes to eliminate all of the warnings, but I can't do anything about these. Is there some option I can use to turn just these warnings off?
To disable:
#pragma warning disable 0162
To restore:
#pragma warning restore 0162
For more on #pragma warning, see MSDN.
Please note that the C# compiler is optimized enough to not emit unreachable code. This is called dead code elimination and it is one of the few optimizations that the C# compiler performs.
And you shouldn't willy-nilly disable the warnings. The warnings are a symptom of a problem. Please see this answer.
First of all, I agree with you, you need to get rid of all warnings. Every little warning you get, get rid of it, by fixing the problem.
Before I go on with what, on re-read, amounts to what looks like a rant, let me emphasis that there doesn't appear to be any performance penalty to using code like this. Having used Reflector to examine code, it appears code that is "flagged" as unreachable isn't actually placed into the output assembly.
It is, however, checked by the compiler. This alone might be a good enough reason to disregard my rant.
In other words, the net effect of getting rid of that warning is just that, you get rid of the warning.
Also note that this answer is an opinion. You might not agree with my opinion, and want to use #pragma to mask out the warning message, but at least have an informed opinion about what that does. If you do, who cares what I think.
Having said that, why are you writing code that won't be reached?
Are you using consts instead of "defines"?
A warning is not an error. It's a note, for you, to go analyze that piece of code and figure out if you did the right thing. Usually, you haven't. In the case of your particular example, you're purposely compiling code that will, for your particular configuration, never execute.
Why is the code even there? It will never execute.
Are you confused about what the word "constant" actually means? A constant means "this will never change, ever, and if you think it will, it's not a constant". That's what a constant is. It won't, and can't, and shouldn't, change. Ever.
The compiler knows this, and will tell you that you have code, that due to a constant, will never, ever, be executed. This is usually an error.
Is that constant going to change? If it is, it's obviously not a constant, but something that depends on the output type (Debug, Release), and it's a "#define" type of thing, so remove it, and use that mechanism instead. This makes it clearer, to people reading your code, what this particular code depends on. Visual Studio will also helpfully gray out the code if you've selected an output mode that doesn't set the define, so the code will not compile. This is what the compiler definitions was made to handle.
On the other hand, if the constant isn't going to change, ever, for any reason, remove the code, you're not going to need it.
In any case, don't fall prey to the easy fix to just disable that warning for that piece of code, that's like taking aspirin to "fix" your back ache problems. It's a short-term fix, but it masks the problem. Fix the underlying problem instead.
To finish this answer, I'm wondering if there isn't an altogether different solution to your problem.
Often, when I see code that has the warning "unreachable code detected", they fall into one of the following categories:
Wrong (in my opinion) usage of const versus a compiler #define, where you basically say to the compiler: "This code, please compile it, even when I know it will not be used.".
Wrong, as in, just plain wrong, like a switch-case which has a case-block that contains both a throw + a break.
Leftover code from previous iterations, where you've just short-circuited a method by adding a return at some point, not deleting (or even commenting out) the code that follows.
Code that depends on some configuration setting (ie. only valid during Debug-builds).
If the code you have doesn't fall under any of the above settings, what is the specific case where your constant will change? Knowing that might give us better ways to answer your question on how to handle it.
What about using preprocessor statements instead?
#if ExecuteThis
DoThis();
#endif
#if ExecuteThat
DoThat();
#endif
Well, #pragma, but that is a but grungy. I wonder if ConditionalAttribute would be better - i.e.
[Conditional("SOME_KEY")]
void DoThis() {...}
[Conditional("SOME_OTHER_KEY")]
void DoThis() {...}
Now calls to DoThis / DoThat are only included if SOME_KEY or SOME_OTHER_KEY are defined as symbols in the build ("conditional compilation symbols"). It also means you can switch between them by changing the configuration and defining different symbols in each.
The fact that you have the constants declared in code tells me that you are recompiling your code with each release you do, you are not using "contants" sourced from your config file.
So the solution is simple:
- set the "constants" (flags) from values stored in your config file
- use conditional compilation to control what is compiled, like this:
#define ExecuteThis
//#define ExecuteThat
public void myFunction() {
#if ExecuteThis
DoThis();
#endif
#if ExecuteThat
DoThat();
#endif
}
Then when you recompile you just uncomment the correct #define statement to get the right bit of code compiled. There are one or two other ways to declare your conditional compilation flags, but this just gives you an example and somewhere to start.
The quickest way to "Just get rid of it" without modifying your code would be to use
#pragma warning disable 0162
On your Namespace, class or method where you want to supress the warning.
For example, this wont throw the warning anymore:
#pragma warning disable 0162
namespace ConsoleApplication4
{
public class Program
{
public const bool something = false;
static void Main(string[] args)
{
if (something) { Console.WriteLine(" Not something" ); }
}
}
However be warn that NO METHOD inside this namespace will throw the warning again... and well.. warnings are there for a reason (what if it happened when you did NOT planned it to be unreachable?)
I guess a safer way would be to write the variables in a configuration file, and read them from there at the beginning of the program, that way you don't even need to recompile to have your different versions/releases! Just change the app file and go :D.
about the speed penalty.. yes.. making it this way would inquire in a speed penalty... compared to using const but unless you are really worried about wating 1/100 of a millisecond more.. I would go for it that way.
Here's a trick:
bool FALSE = false;
if (FALSE) { ...
This will prevent the warning. Wait. I know there's all this "You should not use that, why have code that is not executed?". Answer: Because during development you often need to set up test code. Eventually you will get rid of it. It's important that code it is there during development, but not executed all the time.
Sometimes you want to remove code execution temporarily, for debugging purposes.
Sometimes you want to truncate execution of a function temporarily. You can use this to avoid warnings:
...code..
{ bool TRUE = true; if (TRUE) return; }
...more code...
These things avoid the warning. You might say, if temporary, one should keep the warning in. yes... but again... maybe you should not check it in that way, but temporarily it is useful to get the warning out, for example when spending all day debugging complex collision code.
So, you may ask, why does it matter? Well, these warnings get very annoying when I press F4 to go to the first error, and get some damn 10 warnings first instead and I am knee deep in debugging.
Use the #pragma, you say. Well, that would be a good idea, except that I can't find a way to do that globally on my entire project.. or in a way that will work with Unity3D, which is what I code in C# for. Oh, how useful #include would be.
Never mind, use #if ! Well... yes... but sometimes they are not what you want. They make the code messy and unreadable. You have to bracket your code with them just right. Putting if(false) in front of a block is just so much easier... no need to delimit the block, the braces do that.
What I do is make a nice globally accessible FALSE and TRUE and use them as I need do avoid errors.
And if I want to check if I am actually using them, I can search for all references, or more crudely, but just as effectively, remove them and thus be forced to look at every occurrence of this little trick.
The easiest way is to stop writing unreachable code :D #DontDoThat

How can I introduce sentences and lines of code that will only be executed in debug mode?

I have one application in wich I need to make code changes almost all time (changing crytographic procedures, etc...), so my idea is to have all my debug parameters and variables activated each time I'm making changes. I don't want to be commenting and uncommenting code all the time, so my question refers to simple lines of code that will execute only in debug mode. ¿How can I achieve that?
You may use a conditional code section:
#if DEBUG
//Your code goes here.
#endif
Or, you can use the [Conditional("DEBUG")] attribute to zero out a whole function in a release build.
As in:
[Conditional("DEBUG")]
private void YourFunction()
{
}
Here's a good reference.
http://www.csharphelp.com/archives/archive36.html
From the source, here's a good example:
#if DEBUG
Console.WriteLine("DEBUG is defined");
#else
Console.WriteLine("DEBUG is not defined");
#endif
The two main solutions are preprocessor directives and the Conditional attribute.
The relevant preprocessor directive works as follows:
#if DEBUG
// Lines here are only compiled if DEBUG is defined, like in a Debug build.
#else
// Lines here are only compiled if DEBUG is not defined, like in a Release build.
#endif
The Conditional attribute is applied to a method:
[Conditional("DEBUG")]
public void DoDebugOnly()
{
// Whatever
}
Then all calls to DoDebugOnly() are only compiled when DEBUG is defined.
Both methods work for any other preprocessor identifiers as well. TRACE is another example that is integrated into Visual Studio, but any preprocessor identifier you define works:
#define FOO
#if FOO
// Lines here are only compiled if FOO is defined.
#endif
Depending on what you're trying to do, you may want to consider a logging framework such as log4net or the Logging Application Block. These will let you leave debug messages in your code but will only output them when an external configuration file says to.
If you want to add/remove code that actually performs logic, though, go with the other answers.

Categories

Resources