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
#line
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 5 and 4 and type the answer here:
  • Post
  • My question is why c# defines have the small scope of a file, as someone who comes from a c++ background one of the things I really appreciated is being able to define a debug directive so I can optionally include additional debug information throughout my program and simply remove the directive when I want to do a release build

  • You people are naive.  It's amazing how Microsoft let's ignoramus' design their O/S and languages. BTW, there's nothing managed about managed -- its just targeting an abstracted machine instruction set, and then using the same macro processing "bytecode translations", whose macros are not available to the HLL, to convert it to the actual machine instructions.  Just tell it how it is!

    Both Java and Microsoft are misinformed.  A transistor is already enough of an abstraction, and completely underutilitized and underrespected.

    Furthermore, c# templates, oh excuse me "generics", are a form of macros, so I don't know what you people are talking about.

    I've developed entire assembly language systems on macros that look like a high level language, yet run super fast and have none of the overhead, memory bloat, side-effects and behavioral nuances -- guessing how things really work -- that are much harder to debug.  You can even target different machines and different languages using macros, silly!

    As far as debugging,  you can always expand macros in the listing, so you see the underlying source code anyway.  For example, macro-expanded code could simply be color-coded. duh.  Multi-pass macros are the way to go.

    No, you say, instead it should be a stupid typing contest, where you increase the number of typing mistakes, flipping back and forth around the editor wasting time, "refactoring" slipups, and points of failure in code maintenance!  No wonder there are more service packs than atoms in the universe.

    Simply ignorance, and at a "high level".  You just want "yet another computer language", another proprietary ganglion with all the supporting superstructure.  Just ridiculous.

  • ya ya ya. macros are ugly and bad. we all know it.

    but now I have to implement an algorithm for int16, int32, int64 and decimal

    if i want to change it i have to change it in four places

    much uglier in my opinion.

    I WANT MACROS. YOU DONT LIKE IT? DONT USE IT.

    GIVE ME THE OPTION. DO NOT FORCE ME to write the same code 4 times.

    IT IS THERE FOR A ... REASON!

  • Why doesn't C# have macros like C++? Because its not C++. Want to use macros? Go back to C++. The world is full of programming languages, each one developed with its own philosophy and goals in mind. You should pick the language that is most appropriate for your task and learn that language and its philosophies, not take a language and try to fit it to your philosophies. It would be like driving on the left side of the road and telling the police that they are wrong to not allow you do what you want.

    And remember, never stop learning. Just because you used to do it one way doesn't mean thats the only way to do it.

  • There is definitely a need for a macro language in C#. Declarations of dependency properties is just one example. It would be much nicer if I could create a macro that let me write DEPENDENCY_PROP(int,propProperty,"prop",MyClass) instead of  the usual garbage:

    public static DependencyProperty propProperty = DependencyPropety.Register("prop",typeof etc...

    public  int prop

    {

    get ... etc...

    (

  • Macros are difficult to debug? Yes, but:

    The debugger environment should show the expanded code (which no environment that I know of does), not the actual source (or at least there should be this option).

    (Also searching in code should use that view).

    Some of the comments above suppose certain simple uses of macros.

    But macros can do much more, for instance contain code blocks that begin and end at very different brace levels.

    (Usually such use comes in compensating pairs).

    I agree with the fact that refactoring becomes rather difficult on a combination of macros and tokenizing.

    (This might lead to a need to refactor other names as well).

    But, the environment could warn if refactoring interferes with Macros&Tokenizing (which seldom is the case) and maybe even refuse to refactor such cases.

    Another suggestion is to show both source+expanded (on first example) views (split screen) while editing a macro, which would make it much more easy to design them.

    Much of the ugliness perception comes from the need to mentally expand the macro.

    For printed source, however, the ugliness is there to stay.

    The fact that C# doesn't have a true macro possibility yet, is an opportunity to rethink the concept and design a new&elegant format, for instance not needing the annoying backslash for multiline macros.

    This said, I agree of course that macros (if&when available) should be avoided in C# if more elegant ways to achieve the same can be used.

  • Leave C# clean and use managed C++ if you need for macros.

  • I have a table of User Names which also contain a security level for that user.  I need the text (associated in an enum) with that security level.  

    userTable  = dataTable for Users, passwords, security level, etc.

    Properties.Settings.Default.UserIndex = index of Current User

    SecurityLevelName[] = array of Text for describing Security Level

    (actual case was more complex but I streamlined it a bit for here...)

    I can write (every time!)

    string s =SecurityLevelName[userTable.Rows[Properties.Settings.Default.UserIndex][2];

    or I can write a couple of macros such as'CURRENTUSER(i)' and 'GETSECURITYLEVEL(j)'  (which I only have to debug once; macro definition left to reader) and then write:

    string s = SECURITYLEVELTEXT(CURRENTUSER);

    So which is easier to understand?  Which is easier to write?

    The restrictions imposed tie our hands, stifle our creativity, and force us down paths that are envisioned by a narrow focus and unyielding minds.

    PS

    And Sergei, sometimes we don't always get to choose whether we use C++ or C#.

  • One thing I usually use macros for is debug call wrapping like this (AFAIK works for GCC only):

    #ifdef DEBUG

    #define CALL_WRAP(call) {\

    int result=call;\

    if (result) printf(#call" return an error %i", i); else printf(#call" ok ");\

    result; }\

    #else

    #define CALL_WRAP(call) call

    #endif

    Or, less complex and more portable:

    #ifdef DEBUG

    #define CALL_WRAP(call) printf(#call " return %i", call);

    #else

    #define CALL_WRAP(call) call

    #endif

    Is there a way to do such things in C# without performance loss (e.g being sure call is inline)?

  • You've got to be kidding me. I'm sure you're familiar with the DECLARE_DYNCREATE()  macro used in MFC.  Using macros just eliminates hours of needless repetitive typing. Whoever thought this was a good idea obviously has never programmed in his life.

  • shut up! Microsoft knows better than you do, You shouldn't be using Macros, Bill never had to

  • I can think of a couple of situations where I REALLY NEED macros and C# gives me no reasonable alternative. :( I could care less of the IntelliSense implications.

  • "and in most cases, the JIT will inline them"

    One case where this is false is when using the XNA framework or the JIT on the Xbox360, which NEVER inlines code. This limitation will could cause someone to have to write a pre-processor for C#, which would be avoided by macros.

  • C# has its roots with Borland Delphi. Delphi never had macros and so be c#. I would love to have macros to implement the mechanism for the Debug Statements to disappear from release builds automatically.

  • But MAcros is a grat tool for programmer to write thier code i think C#should have that functions because only programmers can understand what thier code is doing no common peoples

Page 2 of 3 (37 items) 123