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

dka*_*man 17 .net c# conditional-compilation .net-4.0

我可以回想一下,在使用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
Run Code Online (Sandbox Code Playgroud)

Kev*_*oid 12

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

#if NET40
    public Tuple<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#else
    public KeyValuePair<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#endif
Run Code Online (Sandbox Code Playgroud)

预定义符号的列表记录在使用跨平台工具#if 开发库(C# 参考)中:

.NET 框架: NETFRAMEWORK , NET48, NET472, NET471, NET47, NET462, NET461, NET46, NET452, NET451, NET45, NET40, NET35,NET20

.NET 标准: NETSTANDARD , NETSTANDARD2_1, NETSTANDARD2_0, NETSTANDARD1_6, NETSTANDARD1_5, NETSTANDARD1_4, NETSTANDARD1_3, NETSTANDARD1_2, NETSTANDARD1_1,NETSTANDARD1_0

.NET 5+(和.NET Core):NET , NET6_0, NET6_0_ANDROID, NET6_0_IOS, NET6_0_MACOS, NET6_0_MACCATALYST, , NET6_0_TVOS, NET6_0_WINDOWS, NET5_0, NETCOREAPP, NETCOREAPP3_1, NETCOREAPP3_0, NETCOREAPP2_2, NETCOREAPP2_1, NETCOREAPP2_0,NETCOREAPP1_1NETCOREAPP1_0


rmi*_*sen 10

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

  <PropertyGroup Condition="'$(TargetFrameworkVersion)' == 'v4.0'">
    <DefineConstants>$(DefineConstants);DOTNET_40</DefineConstants>
  </PropertyGroup>
  <PropertyGroup>
    <DefineConstants>ITS_CLOBBERING_TIME</DefineConstants>
  </PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

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

    <DefineConstants>$(DefineConstants);ITS_CLOBBERING_TIME</DefineConstants>
Run Code Online (Sandbox Code Playgroud)

此外,您还希望将其放置所有其他PropertyGroup 之后定义的PropertyGroup中,因为Visual Studio 2010当前在自定义编译符号中添加了这样的方式,如果它们放在Visual之前它将会破坏您定义的任何其他自定义编译符号Studio摒弃了它的定义.我已经向微软提交了这个问题.您可以在Microsoft Connect上跟踪其进度.

  • 您甚至不需要有条件地执行此操作,您可以只定义:`<DefineConstants> NETFX $(TargetFrameworkVersion.Replace("v","").Replace(".","_")); $(DefineConstants) )</ DefineConstants>` (3认同)

Bri*_*eon 7

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

  • 构建配置不包括平台和引用的程序集.您必须为每个平台配置不同的项目. (4认同)

Dou*_*oug 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
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 是不是KeyValuePair <TKey,TValue>一个结构? (2认同)