In the C# design, there are a number of cases where we decided on more limited functonality than C++ for the sake of simplicity. One of those decisions was the decision to not support macros.

Thomas wrote that this is something that he really misses.

I know that I’ve run across a few cases where macros would have been really convenient…


I spent about 4 hours last Friday fighting with some code as part of a restructuring I’m doing, and a lot of that time was spent dealing with the fact that somebody defined CoCreateInstance to point to a private wrapper on the function. Part of the time was spent finding that out, and the other part in restructuring include files so that my code could build without that support.

There’s a considerable benefit in looking at code and knowing that is means what it says, without any renaming going on under the covers.

Incidentally, there’s also a benefit in compilation model, in that compiling without a preprocessor is simpler and faster.

Comments (20)

  1. Anders Molin says:

    I also miss macros, a lot!

    I know a lot of people don’t like macros, but used correctly (and carefully) it’s a great tool.

    I also miss pointers but that’s another story 😉 (Yes, I know about unsafe)

  2. Frisky says:

    You know, I have gone through the same macro-Inferno you described. And, while cute, addictive, or even presto-magic cool, I have not found one example yet that could not be done by other means. And, in each case, the solution is clear, more readable, more maintainable, etc.

    Ok, so it is not as cute or cool (like a single line of "C" code that does two thousand things; do people really aspire to do this).

    But, when I code, I know the computer always does what I tell it. It will gulp down 100 lines of code as easily as the one I could have written. The reason I use the longer form is that I am the one (and other humans) that has the trouble understanding and reading it to maintain or increase performance on it. 😉


  3. mschaef says:

    I think macros are a lot like chainsaws: dangerous, but very valuable in specific circumstances. Despite the fact it’s possible to do dangerously stupid things with both, I find them both useful enough I wouldn’t want to give up either.

    The other thing that comes to mind is that eliminating macros doesn’t eliminate all that

    much danger, assuming your language supports other forms of abstraction. After all, you can do stupid, tricky things with functions too:

    int add(int x, y) { return x – y; }

    Rather than give macros up, I think what’s needed are ways to make macros safer and more understandable. An editor that can toggle back and forth at a keystroke between editable source text and an expanded-macro view would go a long way. As a rough start, Lisp languages have a macroexpand function that dumps out macro-processed forms to standard output (in pretty-printed, readable form, depending on the implementaton). Another worthy feature to borrow from Lisp are macros that work at the syntax-tree level rather than the character level. That right there eliminates a lot of the odd syntactic things you have to do to make cpp-style macros behave semi-sensibly. Going a step beyond Lisp, macros in Scheme are hygenic, ie. smart enough to automatically avoid capturing variable names, etc., thus eliminating another source of danger.

    "The reason I use the longer form is that I am the one (and other humans) that has the trouble understanding and reading it to maintain or increase performance on it. ;)"

    The theory is that the author of the macro will develop a macro that adds to readability.

  4. Tim Farley says:

    >> in restructuring include files so that my code could build without that support

    Was it just a macro masking CoCreateInstance itself, or something more complex?

    Because there is a very easy way to bypass a macro that masks a function in C or C++, without having to redefine the macro. Instead of doing this:

    hr = CoCreateInstance(blah blah);

    Do this:

    hr = (CoCreateInstance)(blah blah);

    I like to use this as a bonus trivia question when I’m interviewing a C/C++ candidate.

  5. mschaef says:

    Tim, does that protect against

    #define CoCreateInstance ImSpecialAndIHaveMyOwnCoCreateInstance

    Or just

    #define CoCreateInstance(x, y) ImSpecialAndIHaveMyOwnCoCreateInstance(x, y)


  6. Jonathan Pryor says:

    You’ve only described what’s wrong with macros /as C and C++ implement them/. It’s quite possible to have type-safe, hygenic, non-namespace polluting macros, which would forbid silently replacing CoCreateInstance.

    Just look at Common Lisp, or Scheme, or even Nemerle:

    There is great power to be had in macros. It’s a shame that the C pre-processor makes it so difficult to use them safely (or so easy to misuse them).

  7. I think I’d like a macro like facility in C#, EricG has written a piece here venting his frustration following a piece of macro abuse, so this made me think a bit more about where I’d like them.When I used to work for Borland doing TurboC support I saw mu

  8. I don’t know — how hard would it have been to either

    1) Have some sort of Intellisense hookup to look at what macros are at a glance, or

    2) Limit them so that they can do processing but cannot wrap other APIs?

    Seems like there are ways to make a language richer without corrupting it.

  9. Darren Oakey says:

    I do and don’t miss macros.

    I think most of the time they were abused and used incorrectly. They were also very unsafe, and potentially extremely confusing, as you really didn’t know what a symbol meant.

    However, on the plus side – they gave you, to a limited extent, something that I think is incredibly important – the ability to "extend" the language.

    Some people go with the idea that all code should look consistent. I’d agree with consistency – but I’d rather an internal consistency. It’s far more important to me that someone in the team look at a piece of code and understand it quickly, than someone who just understands C#. Domain specific languages are very important.

    What it comes down to, most companies end up having tons of code which is generated, cut and pasted, or in some other way always the same. Generics go a long way to helping this, but we’ve gone for a long time without them, and it’s not really good enough to say we have to duplicate code, because the language designers haven’t put in feature xyz yet… we NEED the ability to define our own elements of a language. I would argue that however much you care about consistency etc, the words

    DECLARE_COLLECTION( ElementCollection, Element)

    Is more understandable and maintainable to ANYONE than 3 pages of generated collection code for the ElementCollection.

    So… are macros the answer?

    No. Not as written.

    When I’m using .Net, the one other tool I can’t live without is CodeRush. 99% of it I hate and turn off, but one feature makes it the most brilliant productivity tool – templates.

    I type "newtest" space – up comes the attributed definition for a new test function, I just fill in the blanks. I type "_junk property" space and up comes a c# get function that exposes junk.

    What annoys me about it is that now it’s code. Someone can come along and change it – or if for instance, I change the underlying type of a property, I have to also change the property of it’s accessor… that’s just stupid.

    Imagine a version of coderush templates that worked EXACTLY the same way (especially with user definable plugins, we’ve written lots) – but that actually activated at compile time, not edit time. So you could just type:

    newtest MyTest

    "Tests something"




    and it would compile to the the same code as:

    using Daz.Common // at the top

    using nunit.Framework; // at the top


    /// <summary>

    /// Tests Something

    /// </summary>

    public void MyTest()












    and when I type


    It actually compiles as if I said

    using Daz.Common

    using system;




    using Daz.TestSupport

    That would be COOL.

  10. Matthew W. Jackson says:

    Macros could be useful, if they were designed correctly. It shouldn’t be a "preprocessor,"–the compiler should be aware of the macros so that errors can be more easily located.

    As long as it is clear that they are macro expansions and not function calls, I would be happy.

    Perhaps a symbol would have to be placed before a "call" to a macro. Here’s an example where I would love to be able to do:

    public void MyFunction(string myParam)



    //… blah blah blah


    and have it expand to:

    public void MyFunction(string myParam)


    if(myParam == null)

    throw new ArgumentNullException("myParam");

    //… blah blah blah


    As it stands, there’s no way to do this sort of argument check without repeating the word "myParam". Many people believe that this is a sure sign code smell, and I’d have to agree.

  11. Tim Farley says:

    mschaef: My parens trick only protects against this form of macro:

    #define CoCreateInstance(x, y)

    The reason it works is those type of macros must have the left paren right after the name to be expanded, which the intervening right paren blocks. To the compiler itself, the parens around the function name are a no-op.

  12. Peter Ibbotson says:

    Interesting that those of us who miss macros want something like Darrens comment. (I think thats me, Darren, Matthew and Claudio, but then I can’t read italian so I may be wrong there)

    I want to deal with those little code snippets, I seem to spend a lot of time messing around with implementing interfaces, and some sort of macro engine for the boiler plate code would help here.

  13. I haven’t even finished reading the post but I had to comment immediately:

    Please, please never, ever implement macro support in C#.

    My god, when are MS going to understand that less is more, you don’t have to add the kitchen sink to everything?

    Give us a simple, great idea, done well and you will not be suffering all the unflattering comparisons to Apple, Google, et al.


  14. mschaef says:

    "My god, when are MS going to understand that less is more, you don’t have to add the kitchen sink to everything? "

    Macros aren’t the kitchen sink, they’re the means to allow developers to build their own (should they want…)

  15. In questo post di Eric Gunnerson e nei relativi commenti ci sono spunti di riflessione interessanti sull’utilizzo

  16. In short, macros are often times misappropriated when there are better and more consistent means to accomplish…