简体   繁体   English

我可以根据 .NET 框架版本制作预处理器指令吗?

[英]Can I make a preprocessor directive dependent on the .NET framework version?

Here's a concrete example of what I want to do.这是我想做的具体例子。

Consider the string.Join function. Pre-.NET 4.0, there were only two overloads, both of which required a string[] parameter.考虑string.Join function。在 .NET 4.0 之前,只有两个重载,都需要一个string[]参数。

As of .NET 4.0, there are new overloads taking more flexible parameter types, including IEnumerable<string> .从 .NET 4.0 开始,有新的重载采用更灵活的参数类型,包括IEnumerable<string>

I have a library which includes a Join function that does essentially what the .NET 4.0 string.Join function does.我有一个库,其中包含一个Join function,它基本上执行 .NET 4.0 string.Join function 的功能。 I was just wondering if I could make this function's implementation dependent on the .NET framework being targeted.我只是想知道我是否可以使这个函数的实现依赖于目标 .NET 框架。 If 4.0, it could simply call string.Join internally.如果是 4.0,它可以简单地在内部调用string.Join If 3.5 or older, it could call its own internal implementation.如果是 3.5 或更早版本,它可以调用自己的内部实现。

  1. Does this idea make sense?这个想法有意义吗?
  2. If it does make sense, what's the most logical way to do it?如果确实有意义,那么最合乎逻辑的方法是什么? I guess I'm just assuming a preprocessor directive would make the most sense, since a call to string.Join with an IEnumerable<string> parameter won't even compile when targeting a .NET version older than 4.0;我想我只是假设预处理器指令最有意义,因为当目标 .NET 版本早于 4.0 时,使用IEnumerable<string>参数调用string.Join甚至不会编译 so whatever approach I use would have to take place prior to compilation.所以无论我使用什么方法都必须在编译之前进行。 (Checking the Environment.Version property at runtime, for example, wouldn't work.) (例如,在运行时检查Environment.Version属性是行不通的。)

You can take a look at another question on Stack Overflow that illustrates how to set conditional constants through the project file's XML: Detect target framework version at compile time 您可以查看Stack Overflow上的另一个问题,该问题说明了如何通过项目文件的XML设置条件常量: 在编译时检测目标框架版本

Then using that you can determine if you should use the .NET 4 overloads or your own library. 然后使用它可以确定是否应该使用.NET 4重载或您自己的库。

Yes, I think it makes sense (for your particular case, since the change is relatively minor), though obviously that sort of thing could scale out of control fairly quickly. 是的,我认为这是有道理的(对于你的特殊情况,因为变化相对较小),尽管很明显,这种事情可能会很快失控。

IMHO, the most logical way to go about it would be to create different solution/project configurations for each version, then define a custom symbol (say, NET40 ) in your 4.0 configurations, then use that with an #if . 恕我直言,最合乎逻辑的方法是为每个版本创建不同的解决方案/项目配置,然后在4.0配置中定义自定义符号(例如, NET40 ),然后使用#if I'm not certain if configurations will allow you to change the runtime version (that would obviously be the perfect solution), but your worst-case is having to change the version manually. 我不确定配置是否允许您更改运行时版本(这显然是完美的解决方案),但最糟糕的情况是必须手动更改版本。

EDIT: I just saw the answer linked to in Joshua's answer, and that seems like a more streamlined solution, but I'll leave this here anyway, since it does, strictly speaking, answer the question. 编辑:我刚刚看到约书亚答案中的答案,这似乎是一个更简化的解决方案,但无论如何我都会留在这里,因为严格来说,它确实回答了这个问题。

At some point (not sure when), Microsoft added predefined symbols for .NET versions into the MSBuild build system.在某个时候(不确定何时),Microsoft 将 .NET 版本的预定义符号添加到 MSBuild 构建系统中。 Everything here works if you are using MSBuild from the .NET 5+ SDK (even if the project you are building with that SDK is using a much older target framework).如果您使用 .NET 5+ SDK 中的 MSBuild,则这里的一切都有效(即使您使用该 SDK 构建的项目使用的是更旧的目标框架)。

https://learn.microsoft.com/en-us/do.net/csharp/language-reference/preprocessor-directives https://learn.microsoft.com/en-us/do.net/csharp/language-reference/preprocessor-directives

Target Frameworks目标框架 Symbols符号 Additional symbols available in .NET 5+ SDK .NET 5+ SDK 中可用的其他符号
.NET Framework .NET 框架 NETFRAMEWORK,.NET48,.NET472,.NET471,.NET47,.NET462,.NET461,.NET46,.NET452,.NET451,.NET45,.NET40,.NET35,.NET20网络框架、.NET48、.NET472、.NET471、.NET47、.NET462、.NET461、.NET46、.NET452、.NET451、.NET45、.NET40、.NET35、.NET20 NET48_OR_GREATER,.NET472_OR_GREATER,.NET471_OR_GREATER,.NET47_OR_GREATER,.NET462_OR_GREATER,.NET461_OR_GREATER,.NET46_OR_GREATER,.NET452_OR_GREATER,.NET451_OR_GREATER,.NET45_OR_GREATER,.NET40_OR_GREATER,.NET35_OR_GREATER,.NET20_OR_GREATER NET48_OR_GREATER,.NET472_OR_GREATER,.NET471_OR_GREATER,.NET47_OR_GREATER,.NET462_OR_GREATER,.NET461_OR_GREATER,.NET46_OR_GREATER,.NET452_OR_GREATER,.NET451_OR_GREATER,.NET45_OR_GREATERNET,.NET40,_OR_5REATER0,_OR_5REATER
.NET Standard .NET 标准 NETSTANDARD,.NETSTANDARD2_1,.NETSTANDARD2_0,.NETSTANDARD1_6,.NETSTANDARD1_5,.NETSTANDARD1_4,.NETSTANDARD1_3,.NETSTANDARD1_2,.NETSTANDARD1_1,.NETSTANDARD1_0 NETSTANDARD、.NETSTANDARD2_1、.NETSTANDARD2_0、.NETSTANDARD1_6、.NETSTANDARD1_5、.NETSTANDARD1_4、.NETSTANDARD1_3、.NETSTANDARD1_2、.NETSTANDARD1_1、.NETSTANDARD1_0 NETSTANDARD2_1_OR_GREATER,.NETSTANDARD2_0_OR_GREATER,.NETSTANDARD1_6_OR_GREATER,.NETSTANDARD1_5_OR_GREATER,.NETSTANDARD1_4_OR_GREATER,.NETSTANDARD1_3_OR_GREATER,.NETSTANDARD1_2_OR_GREATER,.NETSTANDARD1_1_OR_GREATER,.NETSTANDARD1_0_OR_GREATER NETSTANDARD2_1_OR_GREATER,.NETSTANDARD2_0_OR_GREATER,.NETSTANDARD1_6_OR_GREATER,.NETSTANDARD1_5_OR_GREATER,.NETSTANDARD1_4_OR_GREATER,.NETSTANDARD1_3_OR_GREATER,.NETSTANDARD1_2_OR_GREATER,.NETSTANDARD1_1_OR_GREATER,.NETOR_STANDARDGREATER1
.NET 5+ (and .NET Core) .NET 5+(和 .NET 核心) NET,.NET6_0,.NET5_0,.NETCOREAPP,.NETCOREAPP3_1,.NETCOREAPP3_0,.NETCOREAPP2_2,.NETCOREAPP2_1,.NETCOREAPP2_0,.NETCOREAPP1_1,.NETCOREAPP1_0 NET,.NET6_0,.NET5_0,.NETCOREAPP,.NETCOREAPP3_1,.NETCOREAPP3_0,.NETCOREAPP2_2,.NETCOREAPP2_1,.NETCOREAPP2_0,.NETCOREAPP1_1,.NETCOREAPP1_0 NET6_0_OR_GREATER,.NET5_0_OR_GREATER,.NETCOREAPP3_1_OR_GREATER,.NETCOREAPP3_0_OR_GREATER,.NETCOREAPP2_2_OR_GREATER,.NETCOREAPP2_1_OR_GREATER,.NETCOREAPP2_0_OR_GREATER,.NETCOREAPP1_1_OR_GREATER,.NETCOREAPP1_0_OR_GREATER NET6_0_OR_GREATER,.NET5_0_OR_GREATER,.NETCOREAPP3_1_OR_GREATER,.NETCOREAPP3_0_OR_GREATER,.NETCOREAPP2_2_OR_GREATER,.NETCOREAPP2_1_OR_GREATER,.NETCOREAPP2_0_OR_GREATER,.NETCOREAPP1_1_OR_GREATER,.NETCOREAPP1_0_OR_GREATER

This allows you to, for example, do this:例如,这允许您执行以下操作:

#if NET5_0_OR_GREATER
    Console.WriteLine("This is .NET 5 or later.");
#elif NETCOREAPP
    Console.WriteLine("This is an older version of .NET Core.");
#elif NETFRAMEWORK
    Console.WriteLine("This is the legacy .NET Framework.");
#else
    Console.WriteLine("This is something else.");
#endif

You can prepare your code for .NET 4.0 and write the similar code for the .NET 3.5 base on framework detection . 您可以为.NET 4.0准备代码,并根据框架检测编写.NET 3.5的类似代码。

#if NOT_RUNNING_ON_4
public static class GuidExtensions
{
   public static bool TryParse(this string s, out Guid result)
   {
       if (s.IsNullOrEmpty())
           return null;
       try
       {
          return new Guid(s);
       }
       catch (FormatException)
       {
          return null;
      }
   }
}
#else
    #error switch parsing to .NET 4.0
#endif

And put his line to your *.csproj 并把他的线放到你的* .csproj

<DefineConstants Condition=" '$(TargetFrameworkVersion)' != 'v4.0' ">NOT_RUNNING_ON_4</DefineConstants>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我可以根据C#版本制定预处理器指令吗? - Can I make a preprocessor directive dependent on the C# version? 您可以为 C# 版本添加预处理器指令吗? - Can you add a preprocessor directive for a C# version? 我可以从中央文件设置C#预处理器指令吗? - Can I set a C# preprocessor directive from a central file? asp.net 核心 DI - 我可以让服务依赖于其他服务吗 - asp.net core DI - can I make a service dependent on other services 如何在VS17中更改C#预处理程序指令属性的颜色? - How can I change the color of C# preprocessor directive attribute in VS17? 以编程方式检查.NET Framework版本-我应该吗? - Programatically check for version .NET Framework - Should I? 我可以在版本4.6.2的Visual Studio项目中使用针对4.5.1 .net框架的库吗? - Can I use a library which is targeted to 4.5.1 .net framework in a visual studio project of version 4.6.2 预处理器指令行可以像在 C 中一样在 C# 中使用吗? - Can preprocessor directive lines be used in C# like in C? nuget库中的预处理器指令 - preprocessor directive in nuget library 如何使框架和依赖应用程序松散耦合? - How to make the framework and the dependent applications loosely coupled?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM