Why doesn't C# support #define macros?

Why doesn't C# support #define macros?

Rate This
  • Comments 37

In C++, I can define a macro such as:

#define PRODUCT(x, y, z) x * y * z

and then use it in code:

int a = PRODUCT(3, 2, 1);

C# doesn't allow you to do this. Why?

There are a few reasons why. The first is one of readability.

One of our main design goals for C# is to keep the code very readable. Having the ability to write macros gives the programmer the ability to create their own language - one that doesn't necessarily bear any relation to what the code underneath. To understand what the code does, the user must not only understand how the language works, but he must also understand all of the #define macros that are in effect at that point in time. That makes code much harder to read.

In C#, you can use methods instead of macros, and in most cases, the JIT will inline them, giving you the same performance aspect.

There's also a somewhat more subtle issue. Macros are done textually, which means if I write:

int y = PRODUCT (1 + 2, 3 + 4, 5 + 6)

I would expect to get something that gives me 3 * 7 *11 = 231, but in fact, the expansion as I've defined it gives:

int y = 1 + 2 * 3 + 4 * 5 + 6;

which gives me 33. I can get around that by a judicious application of parenthesis, but its very easy to write a macro that works in some situations and not in others.

Although C# doesn't strictly speaking have a pre-processor, it does have conditional compilation symbols which can be used to affect compilation. These can be defined within code or with parameters to the compiler. The "pre-processing" directives in C# (named solely for consistency with C/C++, despite there being no separate pre-processing step) are (text taken from the ECMA specification):

#define and #undef
Used to define and undefine conditional compilation symbols
#if, #elif, #else and #endif
Used to conditionally skip sections of source code
Used to control line numbers emitted for errors and warnings.
#error and #warning
Used to issue errors and warnings.
#region and #endregion
Used to explicitly mark sections of source code.

See section 9.5 of the ECMA specification for more information on the above. Conditional compilation can also be achieved using the Conditional attribute on a method, so that calls to the method will only be compiled when the appropriate symbol is defined. See section 24.4.2 of the ECMA specifcation for more information on this.

Author: Eric Gunnerson]

Leave a Comment
  • Please add 1 and 3 and type the answer here:
  • Post
  • I doubt that users will read source code of the application. IMO developers should be able to use macro and readability issue has nothing to do with this.
  • Here's a reason that macro's suck! Debugging!! Have you ever had to debug a macro mess? Compiling the code as a debug build doesn't really help you at all, even then you end up effectively with inlined calls and non-type safe code. Maybe there is a way to get the meat of what macros accomplish in a type safe manner that is debuggable and the C# team just hasn't wrapped their heads around it. But I for one believe that with great power comes great responsibliity and as long as C# is aimed at a mainstream audience they should avoid the pre-processor as much as possible.

    Given generics as part of the C# language now I think there is probably little that can't be done with a well designed type safe generic method where a macro would be a preferable implementation.
  • " But I for one believe that with great power comes great responsibliity and as long as C# is aimed at a mainstream audience they should avoid the pre-processor as much as possible."

    I think the point is that we don't have the choice, the decision is made for us. One of the main reasons I gave up on Java was that Sun kept emasculating the language and productivity by telling us what we needed... er hello? :)
  • If you really need macros, just create your code as, say, HelloWorld.csx, then run that through the C preprocessor (CL /C /EP, if memory serves) to produce HelloWorld.cs. NOte that you'll probably loose lots of nice syntax checking, Intellisence and other stuff, so you'd better be sure that you do really, really need them...

    (See also: http://blogs.geekdojo.net/pdbartlett/archive/2004/02/23/1191.aspx where I first "owned up" to having had this idea...)
  • I used to think the lack of macros was a pain, but a little thinking about what you're trying to do usually produces much more intuitive code.

    In C# there are no 'global' or classless methods, macro's would tend to lead to code that doesn't 'fit' into the C# model.

    Also, for algorithmic macros (such as the PRODUCT macro mentioned) a method makes more sense in both the C++ world and the C# world.

    The only real use of macros in the C++ world (IMHO of course) are 'helpers' such as the MFC "BEGIN_MESSAGE_MAP" and friends. These macros reduce code complexity by allowing the author to write code in a more simple way and not worry about the underlying (relatively) complex generated code.

    C# (and the .NET framework in general) has events, reflection and attributes (which can do all sorts of things) that make similar 'magic' management possible, in a much neater way. I no longer miss macros and am glad they're gone.

    Now, templates are another matter... Roll on Whidbey! :)

  • The biggest reason to disallow macros is imho that it makes stuff like automatic refactoring in the IDE possible. If the intellisense had to understand every atrocity that can be commited with macros, it becomes very hard to offer autocompletion. That's why C++ intellisense booster tools like Visual Assist STILL aren't perfect.
  • CC: Personally I don't think that C# should try to be a language for everyone, I applaud their moves up market with the addition of generics and such in Whidbey. But if you're dyning for macros you should check out C++/CLI (Stan has a great blog: http://blogs.msdn.com/slippman). With Microsoft moving to make C++ a fully fledged member of the managed world it becomes worth looking at in my mind as a viable alternative to C# for managed code when C# just won't do exactly what you want.
  • As was mentioned earlier, besides making things harder to read, macros make debugging very painful. I would rather have the C# compiler do a good job of inlining short methods for me rather than creating macros to do that.

    The complexity of the language will continue to increase with new versions, but keeping some of it hidden will help the adoption of C#.
  • >In C++, I can define a macro such as:
    >#define PRODUCT(x, y, z) x * y * z
    >and then use it in code:
    >int a = SUM(3, 2, 1);
    >C# doesn't allow you to do this. Why?

    Neither does C++. You did not define any SUM() function or macro.

  • Macros are only a problem when they act as a textual substitution mechanism. Just be brave, bite the bullet, and put in lisp style macros. ;)
  • People might find Nemerle language (http://nemerle.org) very interesting. I'm developer of its type-safe macro system: it is not a textual transformer, but operates on syntax trees. It can execute any code at compile-time, analyze (decompose) and generate fragments of code. We think it has resolved all drawbacks of preprocessor macros, while giving much more power to them (see http://nemerle.org/macros.html).

    We will also focus on adding debug information to all generated code, so one would have no problems with debugging.
  • In short, macros are often times misappropriated when there are better and more consistent means to accomplish...

  • PingBack from http://www.keyongtech.com/670880-macro-for-__function__-style-information

Page 1 of 3 (37 items) 123