C# 前置處理器指示詞C# preprocessor directives

雖然編譯器沒有另外的前置處理器,但處理本節中所述的指示詞時,會像是有前置處理器一樣。Although the compiler doesn't have a separate preprocessor, the directives described in this section are processed as if there were one. 您可以使用它們來協助進行條件式編譯。You use them to help in conditional compilation. 不同于 C 和 c + + 指示詞,您無法使用這些指示詞來建立宏。Unlike C and C++ directives, you can't use these directives to create macros. 每個前置處理器指示詞都必須是該行中的唯一指令。A preprocessor directive must be the only instruction on a line.

可為 null 的內容Nullable context

預處理器指示詞會 #nullable 設定 可為 null 注釋內容可為 null 的警告內容The #nullable preprocessor directive sets the nullable annotation context and nullable warning context. 這個指示詞會控制可為 null 的注釋是否有效果,以及是否提供可 null 性警告。This directive controls whether nullable annotations have effect, and whether nullability warnings are given. 每個內容都已 停用啟用Each context is either disabled or enabled.

這兩個內容可以在專案層級指定, (在 c # 原始程式碼) 之外。Both contexts can be specified at the project level (outside of C# source code). 指示詞 #nullable 會控制注釋和警告內容,並優先于專案層級的設定。The #nullable directive controls the annotation and warning contexts and takes precedence over the project-level settings. 指示詞會設定) 它控制的 (內容,直到另一個指示詞覆寫它,或直到原始程式檔結束為止。A directive sets the context(s) it controls until another directive overrides it, or until the end of the source file.

指示詞的效果如下所示:The effect of the directives is as follows:

  • #nullable disable:將可為 null 的注釋和警告內容設定為 停用#nullable disable: Sets the nullable annotation and warning contexts to disabled.
  • #nullable enable:將可為 null 的注釋和警告內容設定為 已啟用#nullable enable: Sets the nullable annotation and warning contexts to enabled.
  • #nullable restore:將可為 null 的注釋和警告內容還原至專案設定。#nullable restore: Restores the nullable annotation and warning contexts to project settings.
  • #nullable disable annotations:將可為 null 注釋內容設定為 停用#nullable disable annotations: Sets the nullable annotation context to disabled.
  • #nullable enable annotations:將可為 null 注釋內容設定為 已啟用#nullable enable annotations: Sets the nullable annotation context to enabled.
  • #nullable restore annotations:將可為 null 注釋內容還原至專案設定。#nullable restore annotations: Restores the nullable annotation context to project settings.
  • #nullable disable warnings:將可為 null 的警告內容設定為 停用#nullable disable warnings: Sets the nullable warning context to disabled.
  • #nullable enable warnings:將可為 null 的警告內容設定為 已啟用#nullable enable warnings: Sets the nullable warning context to enabled.
  • #nullable restore warnings:將可為 null 警告內容還原至專案設定。#nullable restore warnings: Restores the nullable warning context to project settings.

條件式編譯Conditional compilation

您可以使用四個預處理器指示詞來控制條件式編譯:You use four preprocessor directives to control conditional compilation:

  • #if:開啟條件式編譯,只有在定義指定的符號時,才會編譯器代碼。#if: Opens a conditional compilation, where code is compiled only if the specified symbol is defined.
  • #elif:關閉上述的條件式編譯,並根據是否已定義指定的符號來開啟新的條件式編譯。#elif: Closes the preceding conditional compilation and opens a new conditional compilation based on if the specified symbol is defined.
  • #else:如果未定義先前指定的符號,則關閉上述條件式編譯,並開啟新的條件式編譯。#else: Closes the preceding conditional compilation and opens a new conditional compilation if the previous specified symbol isn't defined.
  • #endif:關閉上述的條件式編譯。#endif: Closes the preceding conditional compilation.

當 c # 編譯器找到指示詞,最後是指示詞時 #if #endif ,它只會在定義了指定的符號時,才會在指示詞之間編譯器代碼。When the C# compiler finds an #if directive, followed eventually by an #endif directive, it compiles the code between the directives only if the specified symbol is defined. 不同于 C 和 c + +,您無法將數值指派給符號。Unlike C and C++, you can't assign a numeric value to a symbol. #ifC # 中的語句是布林值,而且只會測試是否已定義符號。The #if statement in C# is Boolean and only tests whether the symbol has been defined or not. 例如:For example:

#if DEBUG
    Console.WriteLine("Debug version");
#endif

您可以使用運算子 == (相等) != (不相等) 來測試 booltruefalseYou can use the operators == (equality) and != (inequality) to test for the bool values true or false. true 表示已定義符號。true means the symbol is defined. #if DEBUG 陳述式的意義與 #if (DEBUG == true) 一樣。The statement #if DEBUG has the same meaning as #if (DEBUG == true). 您可以使用 && (和) || (或) ,以及 ! (不) 運算子來評估是否已定義多個符號。You can use the && (and), || (or), and ! (not) operators to evaluate whether multiple symbols have been defined. 您也可以使用括弧來將符號和運算子分組。You can also group symbols and operators with parentheses.

#if以及 #else 、、、和指示詞,可 #elif #endif #define #undef 讓您根據一或多個符號是否存在來包含或排除程式碼。#if, along with the #else, #elif, #endif, #define, and #undef directives, lets you include or exclude code based on the existence of one or more symbols. 在編譯 debug 組建的程式碼時,或針對特定設定編譯時,條件式編譯可能很有用。Conditional compilation can be useful when compiling code for a debug build or when compiling for a specific configuration.

以指示詞開頭的條件指示詞 #if 必須以指示詞明確地結束 #endifA conditional directive beginning with an #if directive must explicitly be terminated with an #endif directive. #define 可讓您定義符號。#define lets you define a symbol. 藉由使用符號做為傳遞給指示詞的運算式 #if ,運算式會評估為 trueBy using the symbol as the expression passed to the #if directive, the expression evaluates to true. 您也可以使用 >defineconstants 編譯器選項來定義符號。You can also define a symbol with the DefineConstants compiler option. 您可以使用取消定義符號 #undefYou can undefine a symbol with #undef. 使用 #define 建立的符號範圍是定義它的檔案。The scope of a symbol created with #define is the file in which it was defined. 您使用 >defineconstants 或 with 定義的符號 #define 不會與相同名稱的變數發生衝突。A symbol that you define with DefineConstants or with #define doesn't conflict with a variable of the same name. 也就是說,不應將變數名稱傳遞給預處理器指示詞,而且符號只能由預處理器指示詞來評估。That is, a variable name shouldn't be passed to a preprocessor directive, and a symbol can only be evaluated by a preprocessor directive.

#elif 可讓您建立複合條件指示詞。#elif lets you create a compound conditional directive. #elif如果上述運算式和先前的選擇性指示詞運算式都不是 #if 評估為,就會評估運算式 #elif trueThe #elif expression will be evaluated if neither the preceding #if nor any preceding, optional, #elif directive expressions evaluate to true. 如果 #elif 運算式評估為 true ,則編譯器會評估 #elif 和下一個條件指示詞之間的所有程式碼。If an #elif expression evaluates to true, the compiler evaluates all the code between the #elif and the next conditional directive. 例如:For example:

#define VC7
//...
#if debug
    Console.WriteLine("Debug build");
#elif VC7
    Console.WriteLine("Visual Studio 7");
#endif

#else 可讓您建立複合條件指示詞,如此一來,如果上述或 (選擇性) 指示詞中的任何運算式都 #if #elif 評估為 true ,則編譯器會評估 #else 和下一個之間的所有程式碼 #endif#else lets you create a compound conditional directive, so that, if none of the expressions in the preceding #if or (optional) #elif directives evaluate to true, the compiler will evaluate all code between #else and the next #endif. #endif (#endif) 必須是接下來的預處理器指示詞 #else#endif(#endif) must be the next preprocessor directive after #else.

#endif 指定以指示詞開頭的條件指示詞結尾 #if#endif specifies the end of a conditional directive, which began with the #if directive.

組建系統也會留意表示 SDK 樣式專案中不同 目標 framework 的預先定義預處理器符號。The build system is also aware of predefined preprocessor symbols representing different target frameworks in SDK-style projects. 當您建立的應用程式可能會以多個 .NET 版本為目標時,它們會很有用。They're useful when creating applications that can target more than one .NET version.

目標 FrameworkTarget Frameworks 符號Symbols
.NET Framework.NET Framework NETFRAMEWORK, NET48, NET472, NET471, NET47, NET462, NET461, NET46, NET452, NET451, NET45, NET40, NET35, NET20NETFRAMEWORK, NET48, NET472, NET471, NET47, NET462, NET461, NET46, NET452, NET451, NET45, NET40, NET35, NET20
.NET Standard.NET Standard NETSTANDARD, NETSTANDARD2_1, NETSTANDARD2_0, NETSTANDARD1_6, NETSTANDARD1_5, NETSTANDARD1_4, NETSTANDARD1_3, NETSTANDARD1_2, NETSTANDARD1_1, NETSTANDARD1_0NETSTANDARD, NETSTANDARD2_1, NETSTANDARD2_0, NETSTANDARD1_6, NETSTANDARD1_5, NETSTANDARD1_4, NETSTANDARD1_3, NETSTANDARD1_2, NETSTANDARD1_1, NETSTANDARD1_0
.NET 5 (和 .NET Core) .NET 5 (and .NET Core) NET, NET5_0, NETCOREAPP, NETCOREAPP3_1, NETCOREAPP3_0, NETCOREAPP2_2, NETCOREAPP2_1, NETCOREAPP2_0, NETCOREAPP1_1, NETCOREAPP1_0NET, NET5_0, NETCOREAPP, NETCOREAPP3_1, NETCOREAPP3_0, NETCOREAPP2_2, NETCOREAPP2_1, NETCOREAPP2_0, NETCOREAPP1_1, NETCOREAPP1_0

注意

針對傳統的非 SDK 樣式專案,您必須透過專案的 [屬性] 頁面,在 Visual Studio 中手動設定不同目標 framework 的條件式編譯符號。For traditional, non-SDK-style projects, you have to manually configure the conditional compilation symbols for the different target frameworks in Visual Studio via the project's properties pages.

其他預先定義的符號包含 DEBUGTRACE 常數。Other predefined symbols include the DEBUG and TRACE constants. 您可以使用 #define 來覆寫為專案所設定的值。You can override the values set for the project using #define. 例如,DEBUG 符號會根據您的組建組態屬性 ("Debug" 或 "Release" 模式) 而自動設定。The DEBUG symbol, for example, is automatically set depending on your build configuration properties ("Debug" or "Release" mode).

下列範例顯示如何 MYTEST 在檔案上定義符號,然後測試 MYTEST 和符號的值 DEBUGThe following example shows you how to define a MYTEST symbol on a file and then test the values of the MYTEST and DEBUG symbols. 此範例的輸出取決於您是在 DebugRelease configuration 模式上建立專案。The output of this example depends on whether you built the project on Debug or Release configuration mode.

#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
    }
}

以下範例說明如何測試不同的目標 Framework,讓您可以盡可能使用較新的 API:The following example shows you how to test for different target frameworks so you can use newer APIs when possible:

public class MyClass
{
    static void Main()
    {
#if NET40
        WebClient _client = new WebClient();
#else
        HttpClient _client = new HttpClient();
#endif
    }
    //...
}

定義符號Defining symbols

您可以使用下列兩個預處理器指示詞來定義或取消定義條件式編譯的符號:You use the following two preprocessor directives to define or undefine symbols for conditional compilation:

  • #define:定義符號。#define: Define a symbol.
  • #undef:取消定義符號。#undef: undefine a symbol.

您可以使用 #define 來定義符號。You use #define to define a symbol. 當您使用符號作為傳遞至指示詞的運算式時 #if ,運算式會評估為 true ,如下列範例所示:When you use the symbol as the expression that's passed to the #if directive, the expression will evaluate to true, as the following example shows:

#define VERBOSE

#if VERBOSE
   Console.WriteLine("Verbose output version");
#endif

注意

如果常數值通常是在 C 和 C++ 中進行宣告,您就不能使用 #define 指示詞進行宣告。The #define directive cannot be used to declare constant values as is typically done in C and C++. 在 C# 中的常數是特別定義為類別或結構的靜態成員。Constants in C# are best defined as static members of a class or struct. 如果您有數個這類常數,請考慮建立個別的「常數」類別來保留它們。If you have several such constants, consider creating a separate "Constants" class to hold them.

符號可以用來指定編譯的條件。Symbols can be used to specify conditions for compilation. 您可以使用或來測試符號 #if #elifYou can test for the symbol with either #if or #elif. 您也可以使用 ConditionalAttribute 執行條件式編譯。You can also use the ConditionalAttribute to perform conditional compilation. 您可以定義符號,但無法指派值給符號。You can define a symbol, but you can't assign a value to a symbol. 如果您要使用的任何指示並不是前置處理器指示詞,則檔案中必須先出現 #define 指示詞才行。The #define directive must appear in the file before you use any instructions that aren't also preprocessor directives. 您也可以使用 >defineconstants 編譯器選項來定義符號。You can also define a symbol with the DefineConstants compiler option. 您可以使用取消定義符號 #undefYou can undefine a symbol with #undef.

定義區域Defining regions

您可以使用下列兩個預處理器指示詞,定義可在大綱中折迭的程式碼區域:You can define regions of code that can be collapsed in an outline using the following two preprocessor directives:

  • #region:啟動區域。#region: Start a region.
  • #endregion:結束區域#endregion: End a region

#region 當您使用程式碼編輯器的 大綱 功能時,可讓您指定可展開或折迭的程式碼區塊。#region lets you specify a block of code that you can expand or collapse when using the outlining feature of the code editor. 在較長的程式碼檔案中,您可以輕鬆地折迭或隱藏一或多個區域,讓您可以將焦點放在目前正在處理的檔案部分。In longer code files, it's convenient to collapse or hide one or more regions so that you can focus on the part of the file that you're currently working on. 下例示範如何定義區域:The following example shows how to define a region:

#region MyClass definition
public class MyClass
{
    static void Main()
    {
    }
}
#endregion

#region區塊必須以指示詞終止 #endregionA #region block must be terminated with an #endregion directive. #region區塊無法與區塊重迭 #ifA #region block can't overlap with an #if block. 不過,區塊 #region 可以嵌套在 #if 區塊中,而且區塊 #if 可以嵌套在 #region 區塊中。However, a #region block can be nested in an #if block, and an #if block can be nested in a #region block.

錯誤和警告資訊Error and warning information

您可以指示編譯器產生使用者定義的編譯器錯誤和警告,並使用下列指示詞來控制行資訊:You instruct the compiler to generate user-defined compiler errors and warnings, and control line information using the following directives:

  • #error:使用指定的訊息產生編譯器錯誤。#error: Generate a compiler error with a specified message.
  • #warning:產生具有特定訊息的編譯器警告。#warning: Generate a compiler warning, with a specific message.
  • #line:變更以編譯器訊息列印的行號。#line: Change the line number printed with compiler messages.

#error 可讓您從您程式碼中的特定位置產生 CS1029 使用者定義錯誤。#error lets you generate a CS1029 user-defined error from a specific location in your code. 例如:For example:

#error Deprecated code in this method.

注意

編譯器會 #error version 以特殊方式處理,並使用包含已使用之編譯器和語言版本的訊息來報告編譯器錯誤 CS8304。The compiler treats #error version in a special way and reports a compiler error, CS8304, with a message containing the used compiler and language versions.

#warning 可讓您從程式碼中的特定位置產生 CS1030 層級一的編譯器警告。#warning lets you generate a CS1030 level one compiler warning from a specific location in your code. 例如:For example:

#warning Deprecated code in this method.

#line 可讓您修改編譯器的行號以及 (選擇性) 錯誤和警告的檔案名稱輸出。#line lets you modify the compiler's line numbering and (optionally) the file name output for errors and warnings.

下列範例示範如何報告兩個與行號建立關聯的警告。The following example shows how to report two warnings associated with line numbers. #line 200 指示詞會將下一行的行號強制為 200 (但預設值為 #6),而且在下一個 #line 指示詞之前,檔案名稱將會回報為 "Special"。The #line 200 directive forces the next line's number to be 200 (although the default is #6), and until the next #line directive, the filename will be reported as "Special". #line default 指示詞會將行編號還原為其預設編號,這會計算已由先前的指示詞重新編號的行。The #line default directive returns the line numbering to its default numbering, which counts the lines that were renumbered by the previous directive.

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;
    }
}

編譯會產生下列輸出:Compilation produces the following output:

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

#line 指示詞可以用於建置程序中的自動化中繼步驟。The #line directive might be used in an automated, intermediate step in the build process. 例如,如果已從原始程式碼檔中移除行,但您仍然想要編譯器根據檔案中的原始行編號來產生輸出,則可以移除行,然後模擬具有 #line 的原始行編號。For example, if lines were removed from the original source code file, but you still wanted the compiler to generate output based on the original line numbering in the file, you could remove lines and then simulate the original line numbering with #line.

#line hidden指示詞會隱藏偵錯工具中的後續程式程式碼,如此一來,當開發人員逐步執行程式碼時,和下一個指示詞之間的任何一行, #line hidden #line (假設它不是其他指示詞 #line hidden) 將會進行。The #line hidden directive hides the successive lines from the debugger, such that when the developer steps through the code, any lines between a #line hidden and the next #line directive (assuming that it isn't another #line hidden directive) will be stepped over. 此選項也可用來讓 ASP.NET 區分使用者定義的程式碼與電腦產生的程式碼。This option can also be used to allow ASP.NET to differentiate between user-defined and machine-generated code. 雖然 ASP.NET 是這項功能的主要取用者,但很可能會有更多來源產生器使用它。Although ASP.NET is the primary consumer of this feature, it's likely that more source generators will make use of it.

指示詞 #line hidden 不會影響錯誤報表中的檔案名或行號。A #line hidden directive doesn't affect file names or line numbers in error reporting. 也就是說,如果編譯器在隱藏區塊中發現錯誤,則編譯器會報告錯誤的目前檔案名和行號。That is, if the compiler finds an error in a hidden block, the compiler will report the current file name and line number of the error.

#line filename 指示詞指定您想要在編譯器輸出中顯示的檔案名稱。The #line filename directive specifies the file name you want to appear in the compiler output. 預設會使用原始程式碼檔的實際名稱。By default, the actual name of the source code file is used. 檔案名稱必須以雙引號 ("") 括住,而且前面必須有行號。The file name must be in double quotation marks ("") and must be preceded by a line number.

下列範例示範偵錯工具如何忽略程式碼中的隱藏行。The following example shows how the debugger ignores the hidden lines in the code. 當您執行範例時,會顯示三行文字。When you run the example, it will display three lines of text. 但是,當您設定中斷點時(如範例所示),然後按 F10 以逐步執行程式碼時,偵錯工具會忽略隱藏的行。However, when you set a break point, as shown in the example, and hit F10 to step through the code, the debugger ignores the hidden line. 即使您在隱藏行設定中斷點,偵錯工具還是會忽略它。Even if you set a break point at the hidden line, the debugger will still ignore it.

// preprocessor_linehidden.cs
using System;
class MainClass
{
    static void Main()
    {
        Console.WriteLine("Normal line #1."); // Set break point here.
#line hidden
        Console.WriteLine("Hidden line.");
#line default
        Console.WriteLine("Normal line #2.");
    }
}

PragmaPragmas

#pragma 將編譯編譯器所在檔案的特殊指示提供給編譯器。#pragma gives the compiler special instructions for the compilation of the file in which it appears. 編譯器必須支援指示。The instructions must be supported by the compiler. 換句話說,您無法使用 #pragma 來建立自訂前置處理指示。In other words, you can't use #pragma to create custom preprocessing instructions.

#pragma pragma-name pragma-arguments

其中 pragma-name 是可辨識 pragma 的名稱,而 pragma-arguments 是 pragma 特定的引數。Where pragma-name is the name of a recognized pragma and pragma-arguments is the pragma-specific arguments.

#pragma warning#pragma warning

#pragma warning 可以啟用或停用特定警告。#pragma warning can enable or disable certain warnings.

#pragma warning disable warning-list
#pragma warning restore warning-list

其中 warning-list 是以逗號分隔的警告編號清單。Where warning-list is a comma-separated list of warning numbers. "CS" 前置詞是選擇性的。The "CS" prefix is optional. 未指定警告編號時,disable 會停用所有警告,而 restore 會啟用所有警告。When no warning numbers are specified, disable disables all warnings and restore enables all warnings.

注意

若要尋找 Visual Studio 中的警告編號,請建立專案,然後在 [輸出] 視窗中尋找警告編號。To find warning numbers in Visual Studio, build your project and then look for the warning numbers in the Output window.

disable會從原始程式檔的下一行開始生效。The disable takes effect beginning on the next line of the source file. 警告會在後面的那一行還原 restoreThe warning is restored on the line following the restore. 如果檔案中沒有 restore ,則會在相同編譯中的任何後續檔案的第一行將警告還原為其預設狀態。If there's no restore in the file, the warnings are restored to their default state at the first line of any later files in the same compilation.

// 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#pragma checksum

產生原始程式檔的總和檢查碼,協助偵錯 ASP.NET 頁面。Generates checksums for source files to aid with debugging ASP.NET pages.

#pragma checksum "filename" "{guid}" "checksum bytes"

其中 "filename" 是需要監視變更或更新的檔案名, "{guid}" 是雜湊演算法 (GUID) 的全域唯一識別碼,而且 "checksum_bytes" 是十六進位數位的字串,代表總和檢查碼的位元組。Where "filename" is the name of the file that requires monitoring for changes or updates, "{guid}" is the Globally Unique Identifier (GUID) for the hash algorithm, and "checksum_bytes" is the string of hexadecimal digits representing the bytes of the checksum. 必須是偶數的十六進位數字。Must be an even number of hexadecimal digits. 奇數的數位會導致編譯時期警告,並且忽略指示詞。An odd number of digits results in a compile-time warning, and the directive is ignored.

Visual Studio 偵錯工具會使用總和檢查碼來確定一定會找到正確的來源。The Visual Studio debugger uses a checksum to make sure that it always finds the right source. 編譯器會計算來源檔案的總和檢查碼,然後將輸出發至程式資料庫 (PDB) 檔案。The compiler computes the checksum for a source file, and then emits the output to the program database (PDB) file. 然後偵錯工具會使用 PDB 比較總和檢查碼計算來源檔案。The debugger then uses the PDB to compare against the checksum that it computes for the source file.

這個解決方案不適用於 ASP.NET 專案,因為計算的總和檢查碼適用于產生的原始程式檔,而不是 .aspx 檔案。This solution doesn't work for ASP.NET projects, because the computed checksum is for the generated source file, rather than the .aspx file. 若要解決這個問題,#pragma checksum 會為 ASP.NET 頁面提供總和檢查碼支援。To address this problem, #pragma checksum provides checksum support for ASP.NET pages.

當您在 Visual C# 中建立 ASP.NET 專案時,所產生原始程式檔會包含來源 .aspx 檔案的總和檢查碼。When you create an ASP.NET project in Visual C#, the generated source file contains a checksum for the .aspx file, from which the source is generated. 接著編譯器會將這項資訊寫入 PDB 檔案中。The compiler then writes this information into the PDB file.

如果編譯器在檔案中找不到 #pragma checksum 指示詞,它會計算總和檢查碼並將值寫入 PDB 檔案。If the compiler doesn't find a #pragma checksum directive in the file, it computes the checksum and writes the value to the PDB file.

class TestClass
{
    static int Main()
    {
        #pragma checksum "file.cs" "{406EA660-64CF-4C82-B6F0-42D48172A799}" "ab007f1d23d9" // New checksum
    }
}