是否可以有条件地编译为.NET Framework版本?

时间:2009-09-20 00:30:04

标签: c# .net .net-4.0 conditional-compilation

我可以回想一下,在使用MFC时,您可以通过检查_MFC_VER宏来支持多个版本的MFC框架。

我现在正在使用.NET 4做一些事情,并希望在几个地方使用Tuple,但仍然保持其他一切3.5兼容。

我正在做类似的事情:

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

5 个答案:

答案 0 :(得分:10)

在.csproj(或理论上为.vbproj)中定义自定义编译符号时,需要注意一点:它们会覆盖所有先前定义的编译符号。例如,请考虑MSBuild代码段:

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

第二个DefineConstants元素,如其值所示,将破坏DefineConstants的第一个值。为避免这种情况,您需要重写第二个DefineConstants元素,如下所示:

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

此外,您需要将此内容放置在所有其他PropertyGroup之后定义的的PropertyGroup中,因为Visual Studio 2010当前会添加自定义编译符号,以便它将破坏任何其他自定义如果在Visual Studio定义之前放置它们,则定义编译符号。我已经向微软提交了这个问题。您可以在Microsoft Connect跟踪其进度。

答案 1 :(得分:7)

您可以使用没有内置预编译器常量。但是,在VS中创建自己的构建配置很容易,每个配置都有自己的一组定义的常量,当然还有目标框架版本。很多人这样做是为了有条件地编译32或64位差异。

答案 2 :(得分:7)

另外,您的条件编译代码会让遇到它的程序员感到沮丧。

根据评论

进行编辑

编写自己的类可能更好,这样你就可以保证它会做什么,而且你没有任何奇怪的签名或继承问题:

public class Pair<TSource, TResult>
{
    public TSource Source { get; set; }
    public TResult Result { get; set; }

    public Pair() {}
    public Pair(TSource source, TResult result)
    {
        Source = source;
        Result = result;
    }

    // Perhaps override Equals() and GetHashCode() as well
}

与往常一样,使用内置内容与推出自己的代码进行权衡是很好的。通常这意味着问自己,“我可以维护和支持这些代码吗?”与“代码是否完成了我需要的东西,开箱即用?”

在这种情况下,由于您不能保证Tuple<T1, T2>,我只需编写您自己的简单版本,以便其他开发人员可以轻松呼吸:)

答案 3 :(得分:1)

由于您应该有不同的项目,您可以拥有部分类,并且只引用每个项目所需的部分类及其特定逻辑:

classname.cs     public partial classname {...}

classname.40.cs     public partial classname {          public Tuple SomeMethod(){...}     }

classname.35.cs     public partial classname {          public KeyValuePair SomeMethod(){...}     }

答案 4 :(得分:0)

如果使用的是.NET Core构建系统,则可以使用其预定义符号:

#if NET40
    public Tuple<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#else
    public KeyValuePair<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#endif

预定义符号列表记录在Developing Libraries with Cross Platform Tools#if (C# Reference)中:

  

.NET Framework NETFRAMEWORKNET20NET35NET40NET45NET451NET452NET46NET461NET462NET47NET471NET472NET48

     

.NET标准: NETSTANDARDNETSTANDARD1_0NETSTANDARD1_1NETSTANDARD1_2NETSTANDARD1_3NETSTANDARD1_4NETSTANDARD1_5NETSTANDARD1_6NETSTANDARD2_0NETSTANDARD2_1

     

.NET Core NETCOREAPPNETCOREAPP1_0NETCOREAPP1_1NETCOREAPP2_0NETCOREAPP2_1NETCOREAPP2_2NETCOREAPP3_0