Dyrektywy preprocesora języka C#
Chociaż kompilator nie ma oddzielnego preprocesora, dyrektywy opisane w tej sekcji są przetwarzane tak, jakby istniały. Są one używane do pomocy w kompilacji warunkowej. W przeciwieństwie do dyrektyw C i C++ nie można używać tych dyrektyw do tworzenia makr. Dyrektywa preprocesora musi być jedyną instrukcją w wierszu.
Kontekst dopuszczany do wartości null
Dyrektywa #nullable
preprocesora ustawia kontekst adnotacji dopuszczającej wartość null i kontekst ostrzeżenia dopuszczającego wartość null. Ta dyrektywa określa, czy adnotacje dopuszczające wartość null mają wpływ i czy są podane ostrzeżenia o wartości null. Każdy kontekst jest wyłączony lub włączony.
Oba konteksty można określić na poziomie projektu (poza kodem źródłowym języka C#), dodając Nullable
element do PropertyGroup
elementu. Dyrektywa #nullable
kontroluje konteksty adnotacji i ostrzeżeń i ma pierwszeństwo przed ustawieniami na poziomie projektu. Dyrektywa ustawia konteksty, które kontroluje do momentu zastąpienia jej przez inną dyrektywę lub do końca pliku źródłowego.
Efekt dyrektyw jest następujący:
-
#nullable disable
: ustawia konteksty adnotacji dopuszczające wartość null i ostrzeżenia na wyłączone. -
#nullable enable
: Ustawia konteksty adnotacji dopuszczające wartość null i ostrzeżenia, które mają być włączone. -
#nullable restore
: przywraca konteksty adnotacji dopuszczające wartość null i ostrzeżenia do ustawień projektu. -
#nullable disable annotations
: ustawia kontekst adnotacji dopuszczalnej wartości null na wyłączony. -
#nullable enable annotations
: Ustawia kontekst adnotacji dopuszczalnej wartości null do włączenia. -
#nullable restore annotations
: przywraca kontekst adnotacji dopuszczania wartości null do ustawień projektu. -
#nullable disable warnings
: ustawia kontekst ostrzeżenia dopuszczający wartość null na wyłączony. -
#nullable enable warnings
: ustawia kontekst ostrzeżenia dopuszczający wartość null, aby był włączony. -
#nullable restore warnings
: przywraca kontekst ostrzeżenia dopuszczający wartość null do ustawień projektu.
Kompilacja warunkowa
Do kontrolowania kompilacji warunkowej używa się czterech dyrektyw preprocesora:
-
#if
: Otwiera kompilację warunkową, w której kod jest kompilowany tylko wtedy, gdy określony symbol jest zdefiniowany. -
#elif
: zamyka poprzednią kompilację warunkową i otwiera nową kompilację warunkową na podstawie tego, czy określony symbol jest zdefiniowany. -
#else
: zamyka poprzednią kompilację warunkową i otwiera nową kompilację warunkową, jeśli poprzedni określony symbol nie jest zdefiniowany. -
#endif
: zamyka poprzednią kompilację warunkową.
Kompilator języka C# kompiluje kod między dyrektywą #if
a #endif
dyrektywą tylko wtedy, gdy określony symbol jest zdefiniowany, lub nie jest zdefiniowany, gdy !
nie jest używany operator. W przeciwieństwie do języka C i C++, nie można przypisać wartości liczbowej do symbolu. Instrukcja #if
w języku C# jest wartością logiczną i sprawdza tylko, czy symbol został zdefiniowany, czy nie. Na przykład następujący kod jest kompilowany, gdy DEBUG
jest zdefiniowany:
#if DEBUG
Console.WriteLine("Debug version");
#endif
Poniższy kod jest kompilowany, gdy MYTEST
nie jest zdefiniowany:
#if !MYTEST
Console.WriteLine("MYTEST is not defined");
#endif
Możesz użyć operatorów ==
(równości) i !=
(nierówności), aby przetestować bool
wartości true
lub false
.
true
oznacza, że symbol jest zdefiniowany. Instrukcja #if DEBUG
ma takie samo znaczenie jak #if (DEBUG == true)
. Aby ocenić, czy zdefiniowano wiele symboli, można użyć &&
operatorów (i), ||
(lub) i !
(nie ). Można również grupować symbole i operatory za pomocą nawiasów.
Poniżej przedstawiono złożoną dyrektywę, która umożliwia kodowi korzystanie z nowszych funkcji platformy .NET przy zachowaniu zgodności z poprzednimi wersjami. Załóżmy na przykład, że używasz pakietu NuGet w kodzie, ale pakiet obsługuje tylko platformę .NET 6 i w górę, a także program .NET Standard 2.0 i nowszy:
#if (NET6_0_OR_GREATER || NETSTANDARD2_0_OR_GREATER)
Console.WriteLine("Using .NET 6+ or .NET Standard 2+ code.");
#else
Console.WriteLine("Using older code that doesn't support the above .NET versions.");
#endif
#if
, wraz z dyrektywami #else
, #elif
, #endif
, #define
i #undef
umożliwia dołączanie lub wykluczanie kodu na podstawie istnienia co najmniej jednego symbolu. Kompilacja warunkowa może być przydatna podczas kompilowania kodu kompilacji debugowania lub kompilowania dla określonej konfiguracji.
Dyrektywa warunkowa rozpoczynająca się od #if
dyrektywy musi zostać jawnie zakończona dyrektywą #endif
.
#define
umożliwia zdefiniowanie symbolu. Używając symbolu jako wyrażenia przekazanego #if
do dyrektywy, wyrażenie zwraca wartość .true
Możesz również zdefiniować symbol za pomocą opcji kompilatora DefineConstants . Możesz usunąć definicję symbolu za pomocą #undef
polecenia . Zakres symbolu utworzonego #define
za pomocą to plik, w którym został zdefiniowany. Symbol zdefiniowany za pomocą elementu DefineConstants lub z elementem #define
nie powoduje konfliktu ze zmienną o tej samej nazwie. Oznacza to, że nazwa zmiennej nie powinna być przekazywana do dyrektywy preprocesora, a symbol może być obliczany tylko przez dyrektywę preprocesora.
#elif
umożliwia utworzenie złożonej dyrektywy warunkowej. Wyrażenie #elif
zostanie obliczone, jeśli wyrażenie nie zostanie obliczone ani z poprzedniego #if
, opcjonalnego wyrażenia #elif
dyrektywy do true
wartości .
#elif
Jeśli wyrażenie zwróci wartość true
, kompilator oblicza cały kod między #elif
i następną dyrektywą warunkową. Na przykład:
#define VC7
//...
#if DEBUG
Console.WriteLine("Debug build");
#elif VC7
Console.WriteLine("Visual Studio 7");
#endif
#else
pozwala utworzyć złożoną dyrektywę warunkową, tak aby, jeśli żadne z wyrażeń w poprzednich #if
lub (opcjonalnych) #elif
dyrektywach daje wartość true
, kompilator oceni cały kod między #else
i następnym #endif
.
#endif
(#endif) musi być następną dyrektywą preprocesora po #else
.
#endif
określa koniec dyrektywy warunkowej, która rozpoczęła się od #if
dyrektywy.
System kompilacji jest również świadomy wstępnie zdefiniowanych symboli preprocesora reprezentujących różne platformy docelowe w projektach w stylu zestawu SDK. Są one przydatne podczas tworzenia aplikacji, które mogą być przeznaczone dla więcej niż jednej wersji platformy .NET.
Platformy docelowe | Symbole | Dodatkowe symbole (dostępne w zestawach .NET 5+ SDK) |
Symbole platformy (dostępne tylko podczas określania programu TFM specyficznego dla systemu operacyjnego) |
---|---|---|---|
.NET Framework |
NETFRAMEWORK , NET481 , , , NET48 NET472 NET471 NET47 NET462 NET461 NET46 NET452 NET451 NET45 NET40 NET35 NET20 |
NET48_OR_GREATER , NET472_OR_GREATER , , , NET471_OR_GREATER NET47_OR_GREATER NET462_OR_GREATER NET461_OR_GREATER NET46_OR_GREATER NET452_OR_GREATER NET451_OR_GREATER NET45_OR_GREATER NET40_OR_GREATER NET35_OR_GREATER NET20_OR_GREATER |
|
.NET Standard |
NETSTANDARD , NETSTANDARD2_1 , , , NETSTANDARD2_0 NETSTANDARD1_6 NETSTANDARD1_5 NETSTANDARD1_4 NETSTANDARD1_3 NETSTANDARD1_2 NETSTANDARD1_1 NETSTANDARD1_0 |
NETSTANDARD2_1_OR_GREATER , NETSTANDARD2_0_OR_GREATER , , NETSTANDARD1_6_OR_GREATER , NETSTANDARD1_5_OR_GREATER NETSTANDARD1_4_OR_GREATER , NETSTANDARD1_3_OR_GREATER , , NETSTANDARD1_2_OR_GREATER NETSTANDARD1_1_OR_GREATER NETSTANDARD1_0_OR_GREATER |
|
.NET 5+ (i .NET Core) |
NET , NET9_0 , , , NET8_0 NET7_0 NET6_0 NET5_0 NETCOREAPP NETCOREAPP3_1 NETCOREAPP3_0 NETCOREAPP2_2 NETCOREAPP2_1 NETCOREAPP2_0 NETCOREAPP1_1 NETCOREAPP1_0 |
NET8_0_OR_GREATER , NET7_0_OR_GREATER , , , NET6_0_OR_GREATER NET5_0_OR_GREATER NETCOREAPP3_1_OR_GREATER NETCOREAPP3_0_OR_GREATER NETCOREAPP2_2_OR_GREATER NETCOREAPP2_1_OR_GREATER NETCOREAPP2_0_OR_GREATER NETCOREAPP1_1_OR_GREATER NETCOREAPP1_0_OR_GREATER |
ANDROID , BROWSER , , IOS , MACCATALYST MACOS , , TVOS , , WINDOWS [OS][version] (na przykład IOS15_1 ),[OS][version]_OR_GREATER (na przykład IOS15_1_OR_GREATER ) |
Uwaga
- Symbole bez wersji są definiowane niezależnie od docelowej wersji.
- Symbole specyficzne dla wersji są definiowane tylko dla docelowej wersji.
- Symbole
<framework>_OR_GREATER
są definiowane dla docelowej wersji i wszystkich wcześniejszych wersji. Jeśli na przykład używasz platformy .NET Framework 2.0, zdefiniowane są następujące symbole:NET20
, ,NET20_OR_GREATER
NET11_OR_GREATER
iNET10_OR_GREATER
. - Symbole
NETSTANDARD<x>_<y>_OR_GREATER
są definiowane tylko dla obiektów docelowych platformy .NET Standard, a nie dla obiektów docelowych implementujących platformę .NET Standard, takich jak .NET Core i .NET Framework. - Różnią się one od obiektów docelowych monikers (TFMs) używanych przez
TargetFramework
MSBuild i NuGet.
Uwaga
W przypadku tradycyjnych projektów innych niż zestaw SDK należy ręcznie skonfigurować symbole kompilacji warunkowej dla różnych platform docelowych w programie Visual Studio za pośrednictwem stron właściwości projektu.
Inne wstępnie zdefiniowane symbole obejmują DEBUG
stałe i .TRACE
Możesz zastąpić wartości ustawione dla projektu przy użyciu polecenia #define
. Na przykład symbol DEBUG jest automatycznie ustawiany w zależności od właściwości konfiguracji kompilacji ("Debugowanie" lub "Wydanie").
W poniższym przykładzie pokazano, jak zdefiniować MYTEST
symbol w pliku, a następnie przetestować wartości MYTEST
symboli i DEBUG
. Dane wyjściowe tego przykładu zależą od tego, czy projekt został utworzony w trybie konfiguracji debugowania , czy wydania .
#define MYTEST
using System;
public class MyClass
{
static void Main()
{
#if (DEBUG && !MYTEST)
Console.WriteLine("DEBUG is defined");
#elif (!DEBUG && MYTEST)
Console.WriteLine("MYTEST is defined");
#elif (DEBUG && MYTEST)
Console.WriteLine("DEBUG and MYTEST are defined");
#else
Console.WriteLine("DEBUG and MYTEST are not defined");
#endif
}
}
W poniższym przykładzie pokazano, jak przetestować różne platformy docelowe, aby w miarę możliwości używać nowszych interfejsów API:
public class MyClass
{
static void Main()
{
#if NET40
WebClient _client = new WebClient();
#else
HttpClient _client = new HttpClient();
#endif
}
//...
}
Definiowanie symboli
Do definiowania lub niezdefiniowania symboli kompilacji warunkowej są używane następujące dwie dyrektywy preprocesora:
-
#define
: Zdefiniuj symbol. -
#undef
: Niezdefiniuj symbol.
#define
Służy do definiowania symbolu. Jeśli używasz symbolu jako wyrażenia przekazanego #if
do dyrektywy, wyrażenie zwróci wartość true
, jak pokazano w poniższym przykładzie:
#define VERBOSE
#if VERBOSE
Console.WriteLine("Verbose output version");
#endif
Uwaga
W języku C# stałe pierwotne powinny być definiowane przy użyciu słowa kluczowego const
. Deklaracja const
tworzy element członkowski static
, którego nie można modyfikować w czasie wykonywania. Dyrektywy #define
nie można używać do deklarowania wartości stałych, ponieważ zwykle odbywa się w językach C i C++. Jeśli masz kilka takich stałych, rozważ utworzenie oddzielnej klasy "Stałe", aby je przechowywać.
Symbole mogą służyć do określania warunków kompilacji. Możesz przetestować symbol za pomocą symbolu #if
lub #elif
. Można również użyć polecenia ConditionalAttribute , aby wykonać kompilację warunkową. Można zdefiniować symbol, ale nie można przypisać wartości do symbolu. Dyrektywa #define
musi pojawić się w pliku przed użyciem instrukcji, które nie są również dyrektywami preprocesora. Możesz również zdefiniować symbol za pomocą opcji kompilatora DefineConstants . Możesz usunąć definicję symbolu za pomocą #undef
polecenia .
Definiowanie regionów
Regiony kodu, które można zwinąć w konspekcie, można zdefiniować przy użyciu następujących dwóch dyrektyw preprocesora:
-
#region
: Uruchom region. -
#endregion
: Kończ region.
#region
Umożliwia określenie bloku kodu, który można rozwinąć lub zwinąć podczas korzystania z funkcji tworzenia konspektowania edytora kodu. W dłuższych plikach kodu wygodne jest zwinięcie lub ukrycie jednego lub większej liczby regionów, dzięki czemu można skupić się na części aktualnie działającego pliku. W poniższym przykładzie pokazano, jak zdefiniować region:
#region MyClass definition
public class MyClass
{
static void Main()
{
}
}
#endregion
Blok #region
musi zostać zakończony dyrektywą #endregion
. Blok #region
nie może nakładać się na #if
blok.
#region
Blok można jednak zagnieżdżać w #if
bloku, a #if
blok można zagnieżdżać w #region
bloku.
Informacje o błędach i ostrzeżeniach
Poinstruuj kompilator, aby wygenerował błędy i ostrzeżenia kompilatora zdefiniowanego przez użytkownika oraz informacje o wierszu sterowania przy użyciu następujących dyrektyw:
-
#error
: Wygeneruj błąd kompilatora z określonym komunikatem. -
#warning
: Wygeneruj ostrzeżenie kompilatora z określonym komunikatem. -
#line
: Zmień numer wiersza wydrukowany za pomocą komunikatów kompilatora.
#error
Umożliwia wygenerowanie błędu zdefiniowanego przez użytkownika CS1029 z określonej lokalizacji w kodzie. Na przykład:
#error Deprecated code in this method.
Uwaga
Kompilator traktuje #error version
w specjalny sposób i zgłasza błąd kompilatora CS8304 z komunikatem zawierającym używany kompilator i wersje językowe.
#warning
umożliwia wygenerowanie ostrzeżenia kompilatora na poziomie CS1030 z określonej lokalizacji w kodzie. Na przykład:
#warning Deprecated code in this method.
#line
Umożliwia zmodyfikowanie numerowania wiersza kompilatora i (opcjonalnie) danych wyjściowych nazwy pliku pod kątem błędów i ostrzeżeń.
W poniższym przykładzie pokazano, jak zgłosić dwa ostrzeżenia skojarzone z numerami wierszy. Dyrektywa #line 200
wymusza numer następnego wiersza na 200 (chociaż wartość domyślna to #6), a do następnej #line
dyrektywy nazwa pliku zostanie zgłoszona jako "Specjalna". Dyrektywa #line default
zwraca numerację wierszy do domyślnej numerowania, która zlicza wiersze, które zostały ponownie numerowane przez poprzednią dyrektywę.
class MainClass
{
static void Main()
{
#line 200 "Special"
int i;
int j;
#line default
char c;
float f;
#line hidden // numbering not affected
string s;
double d;
}
}
Kompilacja generuje następujące dane wyjściowe:
Special(200,13): warning CS0168: The variable 'i' is declared but never used
Special(201,13): warning CS0168: The variable 'j' is declared but never used
MainClass.cs(9,14): warning CS0168: The variable 'c' is declared but never used
MainClass.cs(10,15): warning CS0168: The variable 'f' is declared but never used
MainClass.cs(12,16): warning CS0168: The variable 's' is declared but never used
MainClass.cs(13,16): warning CS0168: The variable 'd' is declared but never used
Dyrektywa #line
może być używana w zautomatyzowanym, pośrednim kroku procesu kompilacji. Jeśli na przykład wiersze zostały usunięte z oryginalnego pliku kodu źródłowego, ale nadal chcesz, aby kompilator wygenerował dane wyjściowe na podstawie oryginalnego numerowania wiersza w pliku, można usunąć wiersze, a następnie zasymulować oryginalne numerowanie wierszy za pomocą #line
polecenia .
Dyrektywa #line hidden
ukrywa kolejne wiersze z debugera, tak aby po przejściu przez dewelopera przez kod wszelkie wiersze między dyrektywą a #line hidden
następną #line
(zakładając, że nie jest to inna #line hidden
dyrektywa) zostaną zastąpione. Tej opcji można również użyć, aby umożliwić ASP.NET rozróżnianie kodu zdefiniowanego przez użytkownika i wygenerowanego przez maszynę. Mimo że ASP.NET jest głównym konsumentem tej funkcji, prawdopodobnie więcej generatorów źródeł będzie z niego korzystać.
#line hidden
Dyrektywa nie ma wpływu na nazwy plików ani numery wierszy w raportowaniu błędów. Oznacza to, że jeśli kompilator znajdzie błąd w ukrytym bloku, kompilator zgłosi bieżącą nazwę pliku i numer wiersza błędu.
Dyrektywa #line filename
określa nazwę pliku, którą chcesz wyświetlić w danych wyjściowych kompilatora. Domyślnie jest używana rzeczywista nazwa pliku kodu źródłowego. Nazwa pliku musi być w podwójnym cudzysłowie ("") i musi być poprzedzona numerem wiersza.
Możesz użyć nowej formy dyrektywy #line
:
#line (1, 1) - (5, 60) 10 "partial-class.cs"
/*34567*/int b = 0;
Składniki tego formularza to:
-
(1, 1)
: wiersz początkowy i kolumna pierwszego znaku w wierszu, który jest zgodny z dyrektywą. W tym przykładzie następny wiersz zostanie zgłoszony jako wiersz 1, kolumna 1. -
(5, 60)
: wiersz końcowy i kolumna dla oznaczonego regionu. -
10
: przesunięcie kolumny dla#line
dyrektywy, która ma obowiązywać. W tym przykładzie 10 kolumna zostanie zgłoszona jako kolumna pierwsza. W tym miejscu rozpoczyna się deklaracjaint b = 0;
. To pole jest opcjonalne. W przypadku pominięcia dyrektywa ma wpływ na pierwszą kolumnę. -
"partial-class.cs"
: nazwa pliku wyjściowego.
Powyższy przykład wygenerowałby następujące ostrzeżenie:
partial-class.cs(1,5,1,6): warning CS0219: The variable 'b' is assigned but its value is never used
Po ponownym mapowania zmiennej b
, znajduje się w pierwszym wierszu, w znaku sześciu znaków pliku partial-class.cs
.
Języki specyficzne dla domeny (DSL) zwykle używają tego formatu, aby zapewnić lepsze mapowanie z pliku źródłowego do wygenerowanych danych wyjściowych języka C#. Najczęstszym zastosowaniem tej rozszerzonej #line
dyrektywy jest ponowne mapowania ostrzeżeń lub błędów, które pojawiają się w wygenerowanym pliku w oryginalnym źródle. Rozważmy na przykład tę stronę razor:
@page "/"
Time: @DateTime.NowAndThen
Właściwość DateTime.Now
została wpisana niepoprawnie jako DateTime.NowAndThen
. Wygenerowany kod C# dla tego fragmentu kodu razor wygląda następująco:page.g.cs
_builder.Add("Time: ");
#line (2, 6) - (2, 27) 15 "page.razor"
_builder.Add(DateTime.NowAndThen);
Dane wyjściowe kompilatora dla poprzedniego fragmentu kodu to:
page.razor(2, 2, 2, 27)error CS0117: 'DateTime' does not contain a definition for 'NowAndThen'
Wiersz 2, kolumna 6 w obiekcie to miejsce, w page.razor
którym rozpoczyna się tekst @DateTime.NowAndThen
. To zanotowano (2, 6)
w dyrektywie. Ta długość @DateTime.NowAndThen
końca w wierszu 2, kolumna 27. To zanotowano w (2, 27)
dyrektywie . Tekst dla DateTime.NowAndThen
elementu rozpoczyna się w kolumnie 15 z page.g.cs
. To zanotowano w 15
dyrektywie . Umieszczenie wszystkich argumentów razem, a kompilator zgłasza błąd w jego lokalizacji w pliku page.razor
. Deweloper może przejść bezpośrednio do błędu w kodzie źródłowym, a nie do wygenerowanego źródła.
Aby wyświetlić więcej przykładów tego formatu, zobacz specyfikację funkcji w sekcji dotyczącej przykładów.
Pragma — dyrektywy
#pragma
udostępnia kompilatorowi specjalne instrukcje dotyczące kompilacji pliku, w którym się pojawia. Instrukcje muszą być obsługiwane przez kompilator. Innymi słowy, nie można użyć #pragma
polecenia do tworzenia niestandardowych instrukcji przetwarzania wstępnego.
-
#pragma warning
: Włącza lub wyłącza ostrzeżenia. -
#pragma checksum
: Generuj sumę kontrolną.
#pragma pragma-name pragma-arguments
Gdzie pragma-name
jest nazwą rozpoznanej pragma i pragma-arguments
jest argumentami specyficznymi dla pragma.
#pragma warning
#pragma warning
może włączać lub wyłączać niektóre ostrzeżenia.
#pragma warning disable warning-list
#pragma warning restore warning-list
Gdzie warning-list
to rozdzielona przecinkami lista numerów ostrzeżeń. Prefiks "CS" jest opcjonalny. Jeśli nie określono żadnych numerów ostrzeżeń, disable
wyłącza wszystkie ostrzeżenia i restore
włącza wszystkie ostrzeżenia.
Uwaga
Aby znaleźć numery ostrzeżeń w programie Visual Studio, skompiluj projekt, a następnie poszukaj numerów ostrzeżeń w oknie Dane wyjściowe .
Element disable
zaczyna się od następnego wiersza pliku źródłowego. Ostrzeżenie zostanie przywrócone w wierszu po .restore
Jeśli nie restore
ma w pliku, ostrzeżenia zostaną przywrócone do stanu domyślnego w pierwszym wierszu wszystkich późniejszych plików w tej samej kompilacji.
// pragma_warning.cs
using System;
#pragma warning disable 414, CS3021
[CLSCompliant(false)]
public class C
{
int i = 1;
static void Main()
{
}
}
#pragma warning restore CS3021
[CLSCompliant(false)] // CS3021
public class D
{
int i = 1;
public static void F()
{
}
}
#pragma checksum
Generuje sumy kontrolne dla plików źródłowych, aby ułatwić debugowanie ASP.NET stron.
#pragma checksum "filename" "{guid}" "checksum bytes"
Gdzie "filename"
jest nazwą pliku, który wymaga monitorowania zmian lub aktualizacji, "{guid}"
jest globalnie unikatowy identyfikator (GUID) algorytmu skrótu i "checksum_bytes"
jest ciągiem cyfr szesnastkowych reprezentujących bajty sumy kontrolnej. Musi być parzystą liczbą cyfr szesnastkowej. Liczba nieparzysta cyfr powoduje wyświetlenie ostrzeżenia w czasie kompilacji, a dyrektywa jest ignorowana.
Debuger programu Visual Studio używa sumy kontrolnej, aby upewnić się, że zawsze znajduje odpowiednie źródło. Kompilator oblicza sumę kontrolną dla pliku źródłowego, a następnie emituje dane wyjściowe do pliku bazy danych programu (PDB). Debuger następnie używa pdB do porównania z sumą kontrolną, którą oblicza dla pliku źródłowego.
To rozwiązanie nie działa w przypadku projektów ASP.NET, ponieważ obliczona suma kontrolna dotyczy wygenerowanego pliku źródłowego, a nie pliku .aspx. Aby rozwiązać ten problem, #pragma checksum
zapewnia obsługę sumy kontrolnej dla stron ASP.NET.
Podczas tworzenia projektu ASP.NET w języku Visual C# wygenerowany plik źródłowy zawiera sumę kontrolną dla pliku .aspx, z którego jest generowane źródło. Kompilator zapisuje te informacje w pliku PDB.
Jeśli kompilator nie znajdzie dyrektywy w pliku, oblicza sumę kontrolną #pragma checksum
i zapisuje wartość w pliku PDB.
class TestClass
{
static int Main()
{
#pragma checksum "file.cs" "{406EA660-64CF-4C82-B6F0-42D48172A799}" "ab007f1d23d9" // New checksum
}
}