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 preprocesora
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 adnotację i flagi ostrzegawcze i ma pierwszeństwo przed ustawieniami na poziomie projektu. Dyrektywa ustawia flagę, którą kontroluje, dopóki inna dyrektywa nie zastąpi jej, lub do końca pliku źródłowego.
Efekt dyrektyw jest następujący:
-
#nullable disable
: ustawia kontekst anulowalności wyłączony. -
#nullable enable
: ustawia kontekst dopuszczalny do wartości null . -
#nullable restore
: przywraca kontekst dopuszczalny do wartości null do ustawień projektu. -
#nullable disable annotations
: ustawia flagę adnotacji w kontekście dopuszczającym wartość null na wyłączoną. -
#nullable enable annotations
: ustawia flagę adnotacji w kontekście dopuszczającym wartości null, aby było włączone. -
#nullable restore annotations
: przywraca flagę adnotacji w kontekście dopuszczalności wartości null do ustawień projektu. -
#nullable disable warnings
: ustawia flagę ostrzegawczą w kontekście dopuszczania wartości null na wyłączoną. -
#nullable enable warnings
: ustawia flagę ostrzeżenia w kontekście obsługującym null, aby był włączony. -
#nullable restore warnings
: przywraca flagę ostrzegawczą w kontekście nullable 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ą.
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").
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. Wyrażenie #if
w języku C# jest logiczne i sprawdza tylko, czy symbol jest zdefiniowany. 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)
. Możesz użyć operatorów &&
(i), ||
(lub)i !
(nie), aby ocenić, czy zdefiniowano wiele symboli. Można również grupować symbole i operatory za pomocą nawiasów.
Poniższy przykład przedstawia 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.
#elif
umożliwia utworzenie złożonej dyrektywy warunkowej. Wyrażenie #elif
jest oceniane, jeśli ani poprzednie wyrażenie dyrektywy #if
, ani poprzednie, opcjonalne wyrażenie dyrektywy #elif
nie równa się true
.
#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.
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 do dyrektywy #if
, wyrażenie zwraca 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
ustala numer następnej linii na 200 (chociaż wartość domyślna to #6), a do następnej dyrektywy #line
nazwa pliku będzie raportowana jako "Special". Dyrektywa #line default
przywraca numerację linii do ustawień domyślnych, które uwzględniają linie 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ę. Chociaż ASP.NET jest głównym odbiorcą tej funkcji, prawdopodobnie więcej generatorów źródeł korzysta z niej.
#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łasza 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ć zgodna z 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)
: Linia początkowa i kolumna pierwszego znaku w linii następującej po dyrektywie. 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. Deklaracjaint b = 0;
zaczyna się od tej kolumny. 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 dyrektywy #line
jest ponowne mapowanie ostrzeżeń lub błędów, które pojawiają się w wygenerowanym pliku do oryginalnego źródła. 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 page.razor
to miejsce, w którym rozpoczyna się tekst @DateTime.NowAndThen
, oznaczany przez (2, 6)
w dyrektywie. Zakres @DateTime.NowAndThen
kończy się w wierszu 2, w kolumnie 27, co jest zaznaczone przez (2, 27)
w dyrektywie. Tekst dla DateTime.NowAndThen
zaczyna się w kolumnie 15 na page.g.cs
, co jest zaznaczone przez 15
w dyrektywie. Kompilator zgłasza błąd w lokalizacji w 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. Kompilator musi obsługiwać używane pragmas. 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 format
i #pragma warning enable format
kontrolują formatowanie bloków kodu w programie Visual Studio.
#pragma warning disable warning-list
#pragma warning restore warning-list
Gdzie warning-list
to rozdzielona przecinkami lista numerów ostrzeżeń, takich jak 414, CS3021
. 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()
{
}
}
Inna forma warning
pragma wyłącza lub przywraca polecenia formatowania programu Visual Studio w blokach kodu:
#pragma warning disable format
#pragma warning restore format
Polecenia formatu programu Visual Studio nie modyfikują tekstu w blokach kodu, w których działa disable format
. Polecenia formatowania, takie jak Ctrl+Ki Ctrl+D, nie modyfikują tych regionów kodu. Ta pragma zapewnia precyzyjną kontrolę nad wizualną prezentacją kodu.
#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
}
}