Condividi tramite


Macros

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...

But...

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

  • Anonymous
    January 31, 2005
    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)

  • Anonymous
    January 31, 2005
    The comment has been removed

  • Anonymous
    January 31, 2005
    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.

  • Anonymous
    January 31, 2005
    >> 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.

  • Anonymous
    January 31, 2005
    Tim, does that protect against

    #define CoCreateInstance ImSpecialAndIHaveMyOwnCoCreateInstance

    Or just

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

    ?

  • Anonymous
    January 31, 2005
    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:
    http://nemerle.org/macros.html
    http://nemerle.org/macrouse.html

    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).

  • Anonymous
    January 31, 2005
    The comment has been removed

  • Anonymous
    January 31, 2005
    The comment has been removed

  • Anonymous
    January 31, 2005
    The comment has been removed

  • Anonymous
    January 31, 2005
    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)
    {
    $ArgumentNotNull(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.

  • Anonymous
    February 01, 2005
    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.

  • Anonymous
    February 01, 2005
    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.

  • Anonymous
    February 03, 2005
    The comment has been removed

  • Anonymous
    February 07, 2005
    The comment has been removed

  • Anonymous
    January 26, 2007
    In questo post di Eric Gunnerson e nei relativi commenti ci sono spunti di riflessione interessanti sull'utilizzo

  • Anonymous
    January 14, 2008
    In short, macros are often times misappropriated when there are better and more consistent means to accomplish...

  • Anonymous
    January 21, 2009
    PingBack from http://www.keyongtech.com/642135-repetivie-try-catch-blocks

  • Anonymous
    May 31, 2009
    PingBack from http://woodtvstand.info/story.php?id=2618