Можно ли условно скомпилировать до версии .NET Framework?

StackOverflow https://stackoverflow.com/questions/1449925

Вопрос

Я могу вспомнить, что при работе с MFC вы могли поддерживать несколько версий MFC framework, проверяя _MFC_VER макрос.

Сейчас я кое-что делаю с .NET 4 и хотел бы использовать Tuple в паре мест, но при этом сохранить совместимость со всем остальным 3.5.

Я хочу сделать что-то вроде:

#if DOTNET4
    public Tuple<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#else
    public KeyValuePair<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#endif
Это было полезно?

Решение

Нет встроенных констант предварительной компиляции, которые вы могли бы использовать.Но достаточно легко создать свои собственные конфигурации сборки в VS, где каждая конфигурация имеет свой собственный набор определенных констант и, конечно, целевую версию фреймворка.Многие люди делают это для условной компиляции на основе 32- или 64-разрядных различий.

Другие советы

Есть одно большое предостережение, о котором следует помнить при определении пользовательских символов компиляции в вашем .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 после все остальные группы свойств, поскольку Visual Studio 2010 в настоящее время добавляет пользовательские символы компиляции таким образом, что они будут заглушать любые другие пользовательские символы компиляции, которые вы определяете, если они будут размещены до того, как Visual Studio завершит свое определение.Я отправил эту проблему в корпорацию Майкрософт.Вы можете отслеживать его прогресс по адресу Microsoft Connect ( Microsoft Connect ).

С другой стороны, ваш код условной компиляции расстроит программистов, которые столкнутся с этим.

Отредактировано на основе комментариев

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

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>, Я бы просто написал ваш собственный простой вариант, чтобы другие разработчики могли вздохнуть спокойно :)

Поскольку у вас должны быть разные проекты, вы могли бы иметь частичные классы и ссылаться только на тот, который вам нужен для каждого проекта, с определенной логикой для них:

имя_класса.cs общедоступное частичное имя_класса { ...}

имя_класса.40.cs общедоступное частичное имя_класса { общедоступный кортеж someMethod(){...} }

имя класса.35.cs открытое частичное имя класса { открытый ключvaluepair someMethod(){...} }

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top