views:

311

answers:

3

I can recall back when working with MFC you could support multiple versions of the MFC framework by checking the _MFC_VER macro.

I'm doing some stuff now with .NET 4 and would like to use Tuple in a couple of spots but still keep everything else 3.5 compatible.

I'm looking to do something like:

#if DOTNET4
    public Tuple<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#else
    public KeyValuePair<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#endif
+4  A: 

There are no builtin precompiler constants that you can use. But, it is easy enough create your own build configurations in VS with each configuration having its own set of defined constants and of course a target framework version. A lot of people do this to conditionally compile based 32 or 64 bit differences.

Brian Gideon
I wonder why they don't build these in like they do DEBUG and CODE_ANALYSIS.
dkackman
dkackman: Eric Lippert always says that these features don't build themselves; the feature does not exist simply because nobody ever designed, specified, implemented, tested, documented and shipped that feature. See http://blogs.msdn.com/ericlippert/archive/2009/06/22/why-doesn-t-c-implement-top-level-methods.aspx
configurator
A build-configuration does not cover Platform and Referenced Assemblies. You will have to configure a different Project for each platform.
Henk Holterman
@configurator: Fair point. It just seems like a logical thing to do for the most common non-build configuration sorts of things (i.e. things that have to be handled at the project level and is a pattern that is already part of vs.net. A compact framework project defines PocketPC automatically for instance.
dkackman
@dkackman: I don't think DEBUG and CODE_ANALYSIS are build in, at least there not automatically defined if you compile with debug or so. For example: DEBUG is explicitly set in the csproj (i.e. msbuild file) when you run the "Debug" configuration.
Christian.K
A: 

There is one big caveat to be aware of when defining custom compilation symbols in your .csproj (or .vbproj, theoretically): they overwrite all previously-defined compilation symbols. For example, consider MSBuild snippet:

  <PropertyGroup Condition="'$(TargetFrameworkVersion)' == 'v4.0'">
    <DefineConstants>$(DefineConstants);DOTNET_40</DefineConstants>
  </PropertyGroup>
  <PropertyGroup>
    <DefineConstants>ITS_CLOBBERING_TIME</DefineConstants>
  </PropertyGroup>

The second DefineConstants element will, as its value suggests, clobber the first value of DefineConstants. To avoid this, you'll want to rewrite the second DefineConstants element to look like this:

    <DefineConstants>$(DefineConstants);ITS_CLOBBERING_TIME</DefineConstants>

Also, you'll want to place this inside of a PropertyGroup defined after all other PropertyGroups, as Visual Studio 2010 currently adds in custom compilation symbols in such a way that it will clobber any other custom compilation symbols you define if they are placed before Visual Studio plops down its definition. I've filed this issue with Microsoft. You can track its progress at Microsoft Connect.

rmiesen
A: 

On a side note, your conditional compilation code will frustrate programmers that encounter it. It's much better to do something like this:

public class Pair<TSource, TResult> :
#if DOTNET4
    Tuple<TSource, TResult>
#else
    KeyValuePair<TSource, TResult>
#endif
{
}

public Pair<TSource, TResult> SomeMethod<TSource, TResult>(){...}

This will ensure that anyone who consumes your code can do this:

Pair<TSource, TResult> result = SomeMethod<TSource, TResult>();

Rather than this:

#if DOTNET4
    Tuple<TSource, TResult> result;
#else
    KeyValuePair<TSource, TResult> result;
#endif

result = SomeMethod<TSource, TResult>();
Doug