Возможно, одной из самых полезных директив препроцессора являются #region и #endregion. Используя эти признаки, вы указываете блок программного кода, который можно скрыть от просмотра и идентифицировать информирующим текстовым маркером. Использование разделов программного кода может упростить обслуживание больших файлов *.cs. Можно, например, создать один раздел для конструкторов типа, другой – для свойств и т.д.
class Car {
private string petName;
private int currSp;
#region Constructors
public Car {…}
public Car Car(int currSp, string petName) {…}
#endregion
#region Properties
public int Speed {…}
public string Name {…}
#endregion
}
При помещений указателя мыши на маркер свернутого раздела вы получите снимок программного кода, спрятанного за соответствующим названием (рис. 9.5).
Рис. 9.5. Разделы программного кода за работой
Условная компиляция
Другой пакет директив препроцессора (#if, #elif, #else, #endif) позволяет выполнить компиляцию блока программного кода по условию, базируясь на предварительно заданных символах. Классическим вариантом использования этих директив является идентификация блока программного кода, который компилируется только при отладке (а не при окончательной компоновке).
class Program
static void Main(string[] args) {
// Этот программный код выполняется только при отладочной
// компиляции проекта.
#if DEBUG
Console.WriteLine("Каталог приложения: {0}", Environment.CurrentDirectory);
Console.WriteLine("Блок: {0}", Environment.MachineName);
Console.WriteLine("ОС: {0}", Environment.OSVersion);
Console.WriteLine("Версия .NET: {0}", Environment.Version);
#endif
}
}
Здесь выполняется проверка на символ DEBUG. Если он присутствует, выводится ряд данных состояния, для чего используются соответствующие статические члены класса System.Environment. Если символ DEBUG не обнаружен, то программный код, размещенный между #if и #endif, компилироваться не будет и в результирующий компоновочный блок не войдет, т.е. будет фактически проигнорирован.
По умолчанию Visual Studio 2005 всегда определяет символ DEBUG, однако такое поведение можно отменить путем снятия отметки флажка Define DEBUG constant (Определить константу DEBUG) на вкладке Build (Сборка), размещенной на странице Properties (Свойства) вашего проекта. В предположении о том, что этот обычно генерируемый символ DEBUG отключен, можно определить этот символ для
#define DEBUG using System;
namespace Preprocessor {
class ProcessMe {
static void Main(string[] args) {
// Программный код, подобный показанному выше…
}
}
}
Замечание. Директивы #define в файле с программным кодом C# должны быть указаны до всех остальных.
Можно также определять свои собственные символы препроцессора. Предположим, например, что у нас есть класс C#, которой должен компилироваться немного иначе в рамках дистрибутива Mono.NET (см. главу 1). Используя #define, можно определить символ MONO_BUILD для каждого файла.
#define DEBUG
#define MONO_BUILD
using System;
namespace Preprocessor {
class Program {
static void Main (string[] args) {
#if MONO_BUILD
Console.WriteLine("Компиляция для Mono!");
Consоlе.WriteLine("Компиляция для Microsoft .NET");
#endif
}
}
}
Чтобы создать символ, применимый для всего проекта, используйте текстовый блок Conditional compilation symbols (Символы условной компиляции, размещенный на вкладке Build (Сборка) страницы свойств проекта (рис. 9.6).
Рис. 9.6. Определение символа препроцессора для применения в рамках всего проекта
Резюме