Могу ли я создать директиву препроцессора, зависящую от версии .NET framework?

Вот конкретный пример того, что я хочу сделать.

Рассмотрим функцию string.Join. Pre -.NET 4.0, было только две перегрузки, для которых требовался параметр string[].

Начиная с .NET 4.0, появляются новые перегрузки с использованием более гибких типов параметров, включая IEnumerable<string>.

У меня есть библиотека, которая включает в себя функцию Join, которая действительно выполняет функцию .NET 4.0 string.Join. Мне просто интересно, могу ли я реализовать эту функцию в зависимости от целевой платформы .NET. Если 4.0, он может просто вызвать string.Join внутренне. Если 3.5 или старше, он может назвать свою внутреннюю реализацию.

  • Имеет ли смысл эта идея?
  • Если это имеет смысл, какой самый логичный способ сделать это? Я предполагаю, что я просто предполагаю, что директива препроцессора будет иметь наибольший смысл, поскольку вызов string.Join с параметром IEnumerable<string> даже не будет компилироваться при таргетинге на версию .NET старше 4.0; поэтому любой подход, который я использую, должен был состояться до компиляции. (Проверка свойства Environment.Version во время выполнения, например, не будет работать.)

Ответ 1

Вы можете взглянуть на другой вопрос о переполнении стека, который иллюстрирует, как установить условные константы в файле проекта XML: Обнаружить версию рамочной платформы во время компиляции

Затем, используя это, вы можете определить, следует ли использовать перегрузки .NET 4 или собственную библиотеку.

Ответ 2

Да, я думаю, что это имеет смысл (для вашего конкретного случая, так как изменение относительно незначительное), хотя очевидно, что такая вещь может быстро выходить из-под контроля.

ИМХО, наиболее логичным путем было бы создание различных конфигураций решений/проектов для каждой версии, затем определение пользовательского символа (например, NET40) в ваших конфигурациях 4.0, а затем использовать его с помощью #if. Я не уверен, что конфигурации позволят вам изменить версию исполнения (что, очевидно, будет идеальным решением), но в худшем случае вам придется вручную менять версию.

EDIT: Я только видел ответ, связанный с ответом Джошуа, и это похоже на более оптимизированное решение, но я оставлю это здесь в любом случае, поскольку он, строго говоря, отвечает вопрос.

Ответ 3

Вы можете подготовить свой код для .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

И поместите свою строку в свой *.csproj

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