C# MACro Definitions in Preprocessor

C# Macro definitions in Preprocessor

No, C# does not support preprocessor macros like C. Visual Studio on the other hand has snippets. Visual Studio's snippets are a feature of the IDE and are expanded in the editor rather than replaced in the code on compilation by a preprocessor.

What's the proper way to emulate C++ macros in C#

If you're at a loss for compile-time cleverness in C#, you're just not abusing expression trees hard enough.

public void LogImage(Expression<Func<Bitmap>> b) {
var memberExpression = b.Body as MemberExpression;
if (memberExpression == null) throw new ArgumentException("Must be invoked with a member reference.");
string name = memberExpression.Member.Name;
Bitmap bitmap = b.Compile()();
LogImage(bitmap, name);
}

Invoked as

ImageLogger?.LogImage(() => processedImage);

There is a bit of overhead associated with producing the expression tree at the call site, even if LogImage is never called, so while this is clever, it's not something to be overused. Also, this requires that your bitmap has a name (getMyProcessedImage() will not work), which is exactly the problem that you would also have with a macro, if C# supported them (nameof(getMyProcessedImage()) is invalid), except that it won't throw an exception until runtime. So it's not so hot in terms of safety either.

Personally, I'd just type the name again. I wouldn't even use nameof, really. Logging images under variable names seems like a dubious practice to me. If I did want a clear reference to the place in the source where the bitmap was produced, I'd use caller info:

public void LogImage(
Bitmap b,
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0
) {
LogImage(b, $"{Path.GetFileNameWithoutExtension(filePath)}({lineNumber})");
}

Invoke simply as

ImageLogger?.LogImage(processedImage);

Of course, this does assume you want unique bitmaps for each location, but given the name "logger" that seems an appropriate assumption.

Is there a way to define a preprocessor macro that includes preprocessor directives?

You cannot define preprocessing directives the way you show in the question.

Yet you may be able to use the _Pragma operator for your purpose:

#if defined __GNUC__ && __GNUC__ >= 8
#define foo _Pragma("GCC unroll 128") _Pragma("GCC ivdep")
#elif defined __clang__
#define foo _Pragma("clang loop vectorize(enable) interleave(enable)")
#else
#define foo
#endif

Why aren't there macros in C#?

from the C# faq.

http://blogs.msdn.com/CSharpFAQ/archive/2004/03/09/86979.aspx

Why doesn't C# support #define macros?
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

Can I have global preprocessor definitions in C# library?

I'd also advise putting the macros in the project settings (csproj file) as @Hans Passant suggests.

If you need the defines documented, you could add a documentation file to the solution explaining what the settings mean.

If there aren't too many variants, you could define a new project configuration for each one. That will allow you to pre-configure the necessary list of #defines for each variant, and then simply switch between them from the configuration combo box in the toolbar. If you want to temporarily disable one option, you could duplicate the current configuration and remove the #define, then delete the config later when you've tested it.

The next option I can suggest to make it "easier" (by combining the settings and docs into a single file as you've suggested) would be to use a simple text file (settings + comments) to configure the project, and spend 15 minutes writing a quick c# app to read this file and write the settings it contains into the .csproj file - it's just XML so should be a trivial app to write. You'd be able to easily tweak this file and run your updater app to chnage the project settings. If it's something you will do often, spend 30 minutes on it and add a UI with checkboxes to choose the settings more easily.

The concept you're describing sounds rather odd, though. The point of a library is usually that you have one standardised lump of code that can be shared by many clients, so changing these sort of defines to reconfigure the whole library a lot is not something that I'd expect to need to do very often. Perhaps you have good reasons, but it may be worth reviewing why you need to solve this #define problem.

(e.g. If you have lots of customers who need different variants of the "library", the best approach will be to use configurations (described above) to allow you to build all needed variants in a batch build. If you are just trying out lots of different algorithms/techniques then can you redesign chunks of the library so that you can restrict the impact of most #defines to just to a single .cs file so they no longer need to be global? Perhaps the library shouldn't be in a single dll, or a plug-in architecture is needed to allow you to pick and choose the "modules" that are included within the library)

C# Preprocessor

Consider taking a look at an aspect-oriented solution like PostSharp, which injects code after the fact based on custom attributes. It's the opposite of a precompiler but can give you the sort of functionality you're looking for (PropertyChanged notifications etc).

Unity C# - Custom #if Preprocessor macro

Namespace imports are resolved at compile time so you need to make sure the assembly containing the namespace is referenced by your project.

You can use conditional preprocessor directives to build different versions of your app (game in this case) with or without a given reference but you need to make sure that the version you are building matches the preprocessor directive and whether it contains the reference assembly or not, for example:

Case 1 - Build a version that do not support "In App purchases"

  1. Remove the package "In app purchasing" in Window -> Package Manager in Unity.
  2. Define a preprocessor directive for case 1 (this must be present before any "using" directive or any code using the in app purcharsing classes.

#undef UnityIAP_Enabled


  1. Wrap the code using #if directives, the code within the block will be ignored during compilation (it will not be even part of your executable, thus, reducing the size of your game)
    #if UnityIAP_Enabled
using UnityEngine.Purchasing;
#endif

  1. Build the game.

Case 2 - Build a version of the app (game) that supports "In App purchases"

Now you do the opposite

  1. Add the package "In app purchasing" in Window -> Package Manager in Unity.
  2. Define preprocessor directive for case 2

#define UnityIAP_Enabled


  1. Build the game.

Edit

You can avoid manually setting the defines in your code by using platform custom #defines as specified here: https://docs.unity3d.com/Manual/PlatformDependentCompilation.html



Related Topics



Leave a reply



Submit