Можно ли условно скомпилировать в версию .NET Framework? - PullRequest
16 голосов
/ 20 сентября 2009

Я могу вспомнить, что при работе с MFC вы могли поддерживать несколько версий инфраструктуры MFC, проверив макрос _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

Ответы [ 4 ]

10 голосов
/ 10 сентября 2010

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

7 голосов
/ 29 сентября 2010

Кстати, ваш код условной компиляции разочарует программистов, которые его встречают.

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

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

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
}

Как всегда, хорошо взвешивать, используя встроенные вещи, а не разворачивать свой собственный код. Обычно это означает, что вы спрашиваете себя: «Я в порядке, поддерживаю и поддерживаю этот код?» vs. "Код делает то, что мне нужно, из коробки?"

В этом случае, поскольку вы не гарантированно получите Tuple<T1, T2>, я бы просто написал свой собственный простой, чтобы другие разработчики могли дышать спокойно:)

7 голосов
/ 20 сентября 2009

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

1 голос
/ 05 августа 2014

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

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

classname.40.cs публичное частичное имя класса { public Tuple SomeMethod () {...} }

classname.35.cs публичное частичное имя класса { public KeyValuePair SomeMethod () {...} }

...