views:

1592

answers:

5

Are there any preprocessor symbols which allow something like

#if CLR_AT_LEAST_3.5
// use ReaderWriterLockSlim
#else
// use ReaderWriterLock
#endif

or some other way to do this?

+13  A: 

I don't think there are any predefined 'preprocessor' symbols. However you can achieve what you want like this:

1) Create different configurations of your project, one for every version of CLR you want to support.

2) Choose a symbol like VERSION2, VERSION3 etc. per CLR version.

3) In every configuration, define the one symbol associated with it and undefine all others.

4) Use these symbols in conditional compilation blocks.

Frederick
+2  A: 

You could manually set this symbol using the /define compiler switch. Then you create different build configurations for each desired clr version.

driAn
+2  A: 

You could use reflection to check dynamically whether a certain type like ReaderWriterLockSlim is available (instead of using the preprocessor).

This would give you the advantage that you can deploy a single version of your product and users having (or updating to) .NET 3.5 will benefit from the optimized code.

0xA3
But it would make using it a complete pig... doable, but not very attractive. In particular, some of the .NET 3.5 features (like Expression) would be *very* hard to use via reflection.
Marc Gravell
Marc, I would not use reflection throughout the code, just to check whether a certain library / type is available on the client machine. This would be very similar to the preprocessor symbols (i.e. an if condition and then branching depending whether 3.5 is there or not)
0xA3
Obviously you would need to cache any reflection results if you go this route.
Alexey Romanov
+4  A: 

There aren't any built in, but you can supply your own.

For this specific scenario, you might want to encapsulate the logic in (for example) a wrapper (lock) class, so that you don't have #if scattered through all the code; of course, if you are only doing a little locking it might not be worth the trouble.

I use different configurations and/or projects to build for a variety of platforms - i.e. protobuf-net builds for .NET 2.0, .NET 3.0, mono, CF 2.0, CF 3.5 using this trick. The code has #if blocks based on different symbols to control logic - so, for example, BinaryFormatter isn't available on CF, WCF is only available with .NET 3.0, Delegate.CreateDelegate isn't on CF 2.0, etc.

Marc Gravell
A: 

If that's all you needed to do, I suppose you could use Environment.Version, but like divo's solution, it does seem to leave a lot of unneccessary code there.

Lucas Jones