C# Language
Dyrektywy preprocesora
Szukaj…
Składnia
- #define [symbol] // Definiuje symbol kompilatora.
- #undef [symbol] // Nie definiuje symbolu kompilatora.
- #warning [komunikat ostrzegawczy] // Generuje ostrzeżenie kompilatora. Przydatne z #if.
- #error [komunikat o błędzie] // Generuje błąd kompilatora. Przydatne z #if.
- #line [numer linii] (nazwa pliku) // Przesłania numer linii kompilatora (i opcjonalnie nazwę pliku źródłowego). Używany z szablonami tekstowymi T4 .
- #pragma ostrzeżenie [wyłącz | przywróć] [numery ostrzegawcze] // Wyłącza / przywraca ostrzeżenia kompilatora.
- #pragma suma kontrolna „ [nazwa pliku] ” „ [guid] ” „ [suma kontrolna] ” // Sprawdza zawartość pliku źródłowego.
- #region [nazwa regionu] // Definiuje składany region kodu.
- #endregion // Kończy blok regionu kodu.
- #if [warunek] // Wykonuje poniższy kod, jeśli warunek jest spełniony.
- #else // Używane po #if.
- #elif [warunek] // Używany po #if.
- #endif // Kończy blok warunkowy rozpoczęty od #if.
Uwagi
Dyrektywy preprocesora są zwykle używane do ułatwienia zmiany programów źródłowych i kompilacji w różnych środowiskach wykonawczych. Dyrektywy w pliku źródłowym nakazują preprocesorowi wykonanie określonych działań. Na przykład preprocesor może zastępować tokeny w tekście, wstawiać zawartość innych plików do pliku źródłowego lub blokować kompilację części pliku, usuwając sekcje tekstu. Linie preprocesora są rozpoznawane i przeprowadzane przed rozszerzeniem makr. Dlatego jeśli makro rozwija się w coś, co wygląda jak polecenie preprocesora, polecenie to nie jest rozpoznawane przez preprocesor.
Instrukcje preprocesora używają tego samego zestawu znaków, co instrukcje pliku źródłowego, z tym wyjątkiem, że sekwencje specjalne nie są obsługiwane. Zestaw znaków używany w instrukcjach preprocesora jest taki sam jak zestaw znaków wykonania. Preprocesor rozpoznaje również ujemne wartości znaków.
Wyrażenia warunkowe
Wyrażenia warunkowe ( #if
, #elif
, etc) czy wspierają ograniczony podzbiór operatorów logicznych. Oni są:
-
==
i!=
. Można ich używać tylko do testowania, czy symbol jest prawdziwy (zdefiniowany) lub fałszywy (nie zdefiniowany) -
&&
,||
,!
-
()
Na przykład:
#if !DEBUG && (SOME_SYMBOL || SOME_OTHER_SYMBOL) && RELEASE == true
Console.WriteLine("OK!");
#endif
skompiluje kod, który wypisuje „OK!” do konsoli, jeśli DEBUG
nie jest zdefiniowany, SOME_SYMBOL
lub SOME_OTHER_SYMBOL
jest zdefiniowany, a RELEASE
jest zdefiniowane.
Uwaga: Podstawienia te są wykonywane w czasie kompilacji i dlatego nie są dostępne do kontroli w czasie wykonywania. Kod wyeliminowany przez użycie #if
nie jest częścią danych wyjściowych kompilatora.
Zobacz także: C # Dyrektywy preprocesora w MSDN.
Wyrażenia warunkowe
Po skompilowaniu następujących elementów, zwróci inną wartość w zależności od zdefiniowanych dyrektyw.
// Compile with /d:A or /d:B to see the difference
string SomeFunction()
{
#if A
return "A";
#elif B
return "B";
#else
return "C";
#endif
}
Wyrażenia warunkowe są zwykle używane do rejestrowania dodatkowych informacji dotyczących kompilacji debugowania.
void SomeFunc()
{
try
{
SomeRiskyMethod();
}
catch (ArgumentException ex)
{
#if DEBUG
log.Error("SomeFunc", ex);
#endif
HandleException(ex);
}
}
Generowanie ostrzeżeń i błędów kompilatora
Ostrzeżenia kompilatora można generować za pomocą dyrektywy #warning
, a błędy można również generować za pomocą dyrektywy #error
.
#if SOME_SYMBOL
#error This is a compiler Error.
#elif SOME_OTHER_SYMBOL
#warning This is a compiler Warning.
#endif
Definiowanie i niezdefiniowanie symboli
Symbol kompilatora to słowo kluczowe zdefiniowane w czasie kompilacji, które można sprawdzić, aby warunkowo wykonać określone sekcje kodu.
Istnieją trzy sposoby zdefiniowania symbolu kompilatora. Można je zdefiniować za pomocą kodu:
#define MYSYMBOL
Można je zdefiniować w Visual Studio, w obszarze Właściwości projektu> Kompilacja> Symbole kompilacji warunkowej:
(Pamiętaj, że DEBUG
i TRACE
mają własne pola wyboru i nie trzeba ich wyraźnie określać).
Lub można je zdefiniować w czasie kompilacji za pomocą przełącznika /define:[name]
na kompilatorze C #, csc.exe
.
Można także niezdefiniować symbole za pomocą dyrektywy #undefine
.
Najbardziej rozpowszechnionym tego przykładem jest symbol DEBUG
, który jest definiowany przez Visual Studio, gdy aplikacja jest kompilowana w trybie debugowania (w porównaniu z trybem wydania).
public void DoBusinessLogic()
{
try
{
AuthenticateUser();
LoadAccount();
ProcessAccount();
FinalizeTransaction();
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Trace.WriteLine("Unhandled exception!");
System.Diagnostics.Trace.WriteLine(ex);
throw;
#else
LoggingFramework.LogError(ex);
DisplayFriendlyErrorMessage();
#endif
}
}
W powyższym przykładzie, gdy wystąpi błąd w logice biznesowej aplikacji, jeśli aplikacja zostanie skompilowana w trybie debugowania (i ustawiony jest symbol DEBUG
), błąd zostanie zapisany w dzienniku śledzenia, a wyjątek zostanie ponownie -rzucony do debugowania. Jeśli jednak aplikacja zostanie skompilowana w trybie Release (i nie zostanie ustawiony żaden symbol DEBUG
), do rejestrowania błędu po cichu zostanie użyte środowisko rejestrowania, a użytkownik końcowy wyświetli przyjazny komunikat o błędzie.
Bloki regionalne
Użyj #region
i #endregion
aby zdefiniować składany region kodu.
#region Event Handlers
public void Button_Click(object s, EventArgs e)
{
// ...
}
public void DropDown_SelectedIndexChanged(object s, EventArgs e)
{
// ...
}
#endregion
Te dyrektywy są korzystne tylko wtedy, gdy IDE obsługujące zwijane regiony (takie jak Visual Studio ) jest używane do edycji kodu.
Inne instrukcje kompilatora
Linia
#line
kontroluje numer linii i nazwę pliku zgłaszane przez kompilator podczas wysyłania ostrzeżeń i błędów.
void Test()
{
#line 42 "Answer"
#line filename "SomeFile.cs"
int life; // compiler warning CS0168 in "SomeFile.cs" at Line 42
#line default
// compiler warnings reset to default
}
Suma kontrolna Pragma
#pragma checksum
umożliwia określenie określonej sumy kontrolnej dla wygenerowanej bazy danych programu (PDB) do debugowania.
#pragma checksum "MyCode.cs" "{00000000-0000-0000-0000-000000000000}" "{0123456789A}"
Korzystanie z atrybutu warunkowego
Dodanie atrybutu Conditional
z System.Diagnostics
nazw System.Diagnostics
do metody to czysty sposób kontrolowania, które metody są wywoływane w twoich kompilacjach, a które nie.
#define EXAMPLE_A
using System.Diagnostics;
class Program
{
static void Main()
{
ExampleA(); // This method will be called
ExampleB(); // This method will not be called
}
[Conditional("EXAMPLE_A")]
static void ExampleA() {...}
[Conditional("EXAMPLE_B")]
static void ExampleB() {...}
}
Wyłączanie i przywracanie ostrzeżeń kompilatora
Możesz wyłączyć ostrzeżenia kompilatora za pomocą #pragma warning disable
i przywrócić je za pomocą #pragma warning restore
:
#pragma warning disable CS0168
// Will not generate the "unused variable" compiler warning since it was disabled
var x = 5;
#pragma warning restore CS0168
// Will generate a compiler warning since the warning was just restored
var y = 8;
Dozwolone są numery rozdzielone przecinkami:
#pragma warning disable CS0168, CS0219
Prefiks CS
jest opcjonalny i można go nawet mieszać (choć nie jest to najlepsza praktyka):
#pragma warning disable 0168, 0219, CS0414
Niestandardowe preprocesory na poziomie projektu
Wygodnie jest ustawić niestandardowe warunkowe przetwarzanie wstępne na poziomie projektu, gdy niektóre działania muszą zostać pominięte, powiedzmy w testach.
Idź do Solution Explorer
-> Kliknij prawym przyciskiem myszy na projekcie, dla którego chcesz ustawić zmienną -> Properties
-> Build
-> Ogólnie znajdź pole Conditional compilation symbols
i wprowadź tutaj zmienną warunkową
Przykład kodu, który pominie jakiś kod:
public void Init()
{
#if !IGNOREREFRESHDB
// will skip code here
db.Initialize();
#endif
}