Альтернативы условной компиляции в C#

какова альтернатива коду с условной компиляцией в C#?

У меня есть класс, который имеет много кода, основанного на конструкции # ifdef .. Через некоторое время мой код не читается.

ищет методы рефакторинга для использования для лучшей читаемости и обслуживания кода со многими #if defs

7 ответов


одно дело-использовать ConditionalAttribute:

[Conditional("DEBUG")]
public void Foo()
{
    // Stuff
}

// This call will only be compiled into the code if the DEBUG symbol is defined
Foo();

Это все еще условная компиляция, но на основе атрибутов, а не #ifdef, что делает его в целом проще.

Другой альтернативой является просто использовать логические значения во время выполнения, а не делать все это во время компиляции. Если бы вы могли дать нам более подробную информацию о том, чего вы пытаетесь достичь и как вы используете условную компиляцию, это было бы полезно.


альтернативой является использование ConditionalAttribute. Условный атрибут работает аналогичным образом.

#define TRACE_ON
using System;
using System.Diagnostics;

public class Trace 
{
    [Conditional("TRACE_ON")]
    public static void Msg(string msg)
    {
        Console.WriteLine(msg);
    }
}  

public class ProgramClass
{
    static void Main()
    {
        Trace.Msg("Now in Main...");
        Console.WriteLine("Done.");
    }
}

Если это проблема с читаемостью кода, Вы можете использовать квалификатор частичного класса .Net и поместить условный код в отдельные файлы, поэтому, возможно, у вас может быть что-то вроде этого...

фу.cs:

public partial class Foo
{
    // Shared Behavior
}

фу.Отлаживать.cs:

#if DEBUG
public partial class Foo
{
    // debug Behavior
}
#endif

фу.бар.cs:

#define BAR
#if BAR
public partial class Foo
{
    // special "BAR" Behavior
}
#endif

Я не уверен, можете ли вы определить свои условия вне файла кода, поэтому сделайте что-то вроде этого может снизить гибкость условных определений (например, вы не сможете создать условную ветвь против бара, скажем, в главном файле, и необходимость поддерживать несколько определенных баров может стать уродливой), а также потребовать определенного dilligence, чтобы перейти к файлам, чтобы эффективно включить/отключить этот бит кода.

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


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


полиморфизм.

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

абстрактные различия в базовый класс или интерфейс.

построить конкретный класс В зависимости от сборки (один #if). Передайте конкретный объект в приложение,а затем приложение вызовет методы, определенные в интерфейсе.


Если причина, по которой вы используете условную компиляцию, может быть легко переработана, вы можете использовать Управляемая Платформа Расширяемости для динамической загрузки кода на основе условий во время выполнения.


расширение на ответ Джона, в то время как существует ряд ограничений на использование ConditionalAttribute, есть значительное преимущество. Если условие равно false, вызовы условного метода опущены. Например, вы можете добавить 100 вызовов в систему ведения журнала, например для отладки, которые могут быть условно исключены из производственного кода. Когда они исключены, нет никаких накладных расходов, связанных с вызовом метода, который не нужно вызывать. Используя #ifdef, вам придется обернуть каждый вызов в систему регистрации, чтобы условно исключить их.

обратите внимание, что это работает только между сборками, если вызывающий условный метод повторно скомпилирован.