20

我记得在使用 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
4

5 回答 5

11

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.

于 2010-09-10T04:34:36.937 回答
7

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

于 2009-09-20T00:34:47.620 回答
7

On a side note, your conditional compilation code will frustrate programmers that encounter it.

Edited, based on comments

It's probably better to write your own class so you can guarantee what it's going to do, and you don't have any weird signature or inheritance issues:

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
}

As always, it's good to weigh using the built-in stuff vs. rolling out your own code. Generally that means asking yourself, "Am I OK maintaining and supporting this code?" vs. "Does the code do what I need it to, out of the box?"

In this case, since you're not guaranteed to have Tuple<T1, T2>, I'd just write your own simple one so other developers can breathe easy :)

于 2010-09-29T15:22:57.363 回答
4

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

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

使用跨平台工具#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_1,NETCOREAPP1_0

于 2019-11-21T17:01:28.520 回答
1

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

classname.cs 公共部分类名 { ... }

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

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

于 2014-08-05T02:54:31.807 回答