diff --git a/docs/csharp/language-reference/configure-language-version.md b/docs/csharp/language-reference/configure-language-version.md index 5e3f324de774d..71d5e2e70dc7c 100644 --- a/docs/csharp/language-reference/configure-language-version.md +++ b/docs/csharp/language-reference/configure-language-version.md @@ -2,22 +2,24 @@ title: Configure language version description: Learn how to override the default C# language version manually. The C# compiler can support any language version up to the version in the installed SDK. ms.custom: "updateeachrelease" -ms.date: 01/31/2025 +ms.date: 01/16/2026 --- # Configure C# language version -The information in this article applies to .NET 5 and above. For UWP projects, see this information in the article on [Choosing a UWP version](/windows/uwp/updates-and-versions/choose-a-uwp-version). +The information in this article applies to .NET 5 and later. For UWP projects, see the article on [Choosing a UWP version](/windows/uwp/updates-and-versions/choose-a-uwp-version). -In Visual Studio, the option to change the language version through the UI is disabled because the default version is aligned with the project's target framework (`TFM`). This default configuration ensures compatibility between language features and runtime support. To change the language version in Visual Studio, change the project's target framework. +[!INCLUDE[csharp-version-note](./includes/initial-version.md)] + +In Visual Studio, the option to change the language version through the UI is disabled because the default version aligns with the project's target framework (`TFM`). This default configuration ensures compatibility between language features and runtime support. To change the language version in Visual Studio, change the project's target framework. For example, changing the target `TFM` (for example, from [.NET 6](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) to [.NET 9](https://dotnet.microsoft.com/en-us/download/dotnet/9.0)) updates the language version accordingly, from C# 10 to C# 13. This approach prevents issues with runtime compatibility and minimizes unexpected build errors due to unsupported language features. -If you need a specific language version that differs from the one automatically selected, refer to the methods in this article to override the default settings directly in the project file. +If you need a specific language version that differs from the one automatically selected, use the methods in this article to override the default settings directly in the project file. > [!WARNING] > -> Setting the `LangVersion` element to `latest` is discouraged. The `latest` setting means the installed compiler uses its latest version. The value of `latest` can change from machine to machine, making builds unreliable. In addition, it enables language features that might require runtime or library features not included in the current SDK. +> Don't set the `LangVersion` element to `latest`. The `latest` setting means the installed compiler uses its latest version. The value of `latest` can change from machine to machine, making builds unreliable. In addition, it enables language features that might require runtime or library features not included in the current SDK. If you must specify your C# version explicitly, you can do so in several ways: @@ -32,7 +34,7 @@ If you must specify your C# version explicitly, you can do so in several ways: ## Edit the project file -You can set the language version in your project file. The project file is the `*.csproj` file in the root folder for your project. For example, if you explicitly want access to preview features, add an element like the following example: +Set the language version in your project file. The project file is the `*.csproj` file in the root folder for your project. For example, if you want explicit access to preview features, add an element like the following example: ```xml @@ -44,7 +46,7 @@ The value `preview` uses the latest available preview C# language version your c ## Configure multiple projects -To configure multiple C# projects, you can create a *Directory.Build.props* file, typically in your solution directory, that contains the `` element. Add the following setting to the *Directory.Build.props* file: +To configure multiple C# projects, create a *Directory.Build.props* file, typically in your solution directory, that contains the `` element. Add the following setting to the *Directory.Build.props* file: ```xml @@ -58,13 +60,13 @@ Builds in all subdirectories of the directory containing that file now use the p > [!NOTE] > -> The versions for C# and VB are different. Don't use the *Directory.Build.Props* file for a folder where subdirectories contain projects for both languages. The versions don't match. +> The versions for C# and Visual Basic are different. Don't use the *Directory.Build.Props* file for a folder where subdirectories contain projects for both languages. The versions don't match. ## C# language version reference > [!IMPORTANT] > -> Using a C# language version newer than the version associated with your target TFM is unsupported. +> Using a C# language version newer than the version associated with your target TFM isn't supported. The following table shows all current C# language versions. Older compilers might not understand every value. If you install the latest .NET SDK, you have access to everything listed. diff --git a/docs/csharp/language-reference/language-versioning.md b/docs/csharp/language-reference/language-versioning.md index 18d9290927625..ab9665c33cb40 100644 --- a/docs/csharp/language-reference/language-versioning.md +++ b/docs/csharp/language-reference/language-versioning.md @@ -2,16 +2,18 @@ title: Language versioning description: Learn about how the C# language version is determined based on your project and the reasons behind that choice. ms.custom: "updateeachrelease" -ms.date: 09/17/2024 +ms.date: 01/16/2026 --- # C# language versioning -The latest C# compiler determines a default language version based on your project's target framework or frameworks. Visual Studio doesn't provide a UI to change the value, but you can change it by editing the *csproj* file. The choice of default ensures that you use the latest language version compatible with your target framework. You benefit from access to the latest language features compatible with your project's target. This default choice also ensures you don't use a language that requires types or runtime behavior not available in your target framework. Choosing a language version newer than the default can cause hard to diagnose compile-time and runtime errors. +The latest C# compiler determines a default language version based on your project's target framework or frameworks. Visual Studio doesn't provide a UI to change the value, but you can change it by editing the *csproj* file. The choice of default ensures that you use the latest language version compatible with your target framework. You benefit from access to the latest language features compatible with your project's target. This default choice also ensures you don't use a language version that requires types or runtime behavior unavailable in your target framework. Choosing a language version newer than the default can cause hard-to-diagnose compile-time and runtime errors. + +[!INCLUDE[csharp-version-note](./includes/initial-version.md)] [C# 14](../whats-new/csharp-14.md) is supported only on .NET 10 and newer versions. [C# 13](../whats-new/csharp-13.md) is supported only on .NET 9 and newer versions. [C# 12](../whats-new/csharp-12.md) is supported only on .NET 8 and newer versions. Using a C# language version newer than the version associated with your target TFM is unsupported. -Check the [Visual Studio platform compatibility](/visualstudio/releases/2022/compatibility#-visual-studio-2022-support-for-net-development) page for details on which .NET versions are supported by versions of Visual Studio. Check the [Mono page for C#](https://www.mono-project.com/docs/about-mono/languages/csharp/) for Mono compatibility with C# versions. +For details on which .NET versions are supported by versions of Visual Studio, see the [Visual Studio platform compatibility](/visualstudio/releases/2026/compatibility#-visual-studio-support-for-net-development) page. ## Defaults diff --git a/docs/csharp/language-reference/preprocessor-directives.md b/docs/csharp/language-reference/preprocessor-directives.md index 307e0110639a7..814ba59bfb0ac 100644 --- a/docs/csharp/language-reference/preprocessor-directives.md +++ b/docs/csharp/language-reference/preprocessor-directives.md @@ -1,7 +1,7 @@ --- description: "Learn the different C# preprocessor directives that control conditional compilation, warnings, nullable analysis, and more" title: "Preprocessor directives" -ms.date: 09/24/2025 +ms.date: 01/16/2026 f1_keywords: - "cs.preprocessor" - "#nullable" @@ -43,22 +43,24 @@ helpviewer_keywords: --- # 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. 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. +Although the compiler doesn't have a separate preprocessor, it processes the directives described in this section as if there were one. Use these directives to help in conditional compilation. 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. + +[!INCLUDE[csharp-version-note](./includes/initial-version.md)] ## File-based apps -*File-based apps* are programs that are compiled and run using `dotnet run Program.cs` (or any `*.cs` file). The C# compiler ignores these preprocessor directives, but the build system parses them to produce the output. These directives generate warnings when encountered in a project-based compilation. +*File-based apps* are programs that you compile and run by using `dotnet run Program.cs` (or any `*.cs` file). The C# compiler ignores these preprocessor directives, but the build system parses them to produce the output. These directives generate warnings when encountered in a project-based compilation. The C# compiler ignores any preprocessor directive that starts with `#:` or `#!`. -The `#!` preprocessor directive enables unix shells to directly execute a C# file using `dotnet run`. For example: +The `#!` preprocessor directive enables Unix shells to directly execute a C# file by using `dotnet run`. For example: ```csharp #!/usr/bin/env dotnet run Console.WriteLine("Hello"); ``` -The preceding code snippet informs a Unix shell to execute the file using `dotnet run`. The `/usr/bin/env` command locates the `dotnet` executable in your PATH, making this approach portable across different Unix and macOS distributions. The `#!` line must be the first line in the file, and the following tokens are the program to run. You need to enable the *execute* (`x`) permission on the C# file for that feature. +The preceding code snippet informs a Unix shell to execute the file by using `dotnet run`. The `/usr/bin/env` command locates the `dotnet` executable in your PATH, making this approach portable across different Unix and macOS distributions. The `#!` line must be the first line in the file, and the following tokens are the program to run. You need to enable the *execute* (`x`) permission on the C# file for that feature. The `#:` directives that are used in file-based apps are described in the [file based apps reference](../../core/sdk/file-based-apps.md). @@ -66,9 +68,9 @@ Other tools can add new tokens following the `#:` convention. ## Nullable context -The `#nullable` preprocessor directive sets the *annotations* and *warning* flags in the *nullable context*. This directive controls whether nullable annotations have effect, and whether nullability warnings are given. Each flag is either *disabled* or *enabled*. +The `#nullable` preprocessor directive sets the *annotations* and *warning* flags in the *nullable context*. This directive controls whether nullable annotations have effect, and whether nullability warnings are given. Each flag is either *disabled* or *enabled*. -Both contexts can be specified at the project level (outside of C# source code) adding the [`Nullable`](./compiler-options/language.md#nullable) element to the `PropertyGroup` element. The `#nullable` directive controls the annotation and warning flags and takes precedence over the project-level settings. A directive sets the flag it controls until another directive overrides it, or until the end of the source file. +You can specify both contexts at the project level (outside of C# source code) by adding the [`Nullable`](./compiler-options/language.md#nullable) element to the `PropertyGroup` element. The `#nullable` directive controls the annotation and warning flags and takes precedence over the project-level settings. A directive sets the flag it controls until another directive overrides it, or until the end of the source file. The effect of the directives is as follows: @@ -84,9 +86,9 @@ The effect of the directives is as follows: ## Conditional compilation -You use four preprocessor directives to control conditional compilation: +Use four preprocessor directives to control conditional compilation: -- `#if`: Opens a conditional compilation, where code is compiled only if the specified symbol is defined. +- `#if`: Starts a conditional compilation. The compiler compiles the code only if the specified symbol is defined. - `#elif`: Closes the preceding conditional compilation and opens a new conditional compilation based on if the specified symbol is defined. - `#else`: Closes the preceding conditional compilation and opens a new conditional compilation if the previous specified symbol isn't defined. - `#endif`: Closes the preceding conditional compilation. @@ -98,9 +100,9 @@ The build system is also aware of predefined preprocessor symbols representing d > [!NOTE] > 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. -Other predefined symbols include the `DEBUG` and `TRACE` constants. You can override the values set for the project using `#define`. The DEBUG symbol, for example, is automatically set depending on your build configuration properties ("Debug" or "Release" mode). +Other predefined symbols include the `DEBUG` and `TRACE` constants. Use `#define` to override the values set for the project. The `DEBUG` symbol, for example, is automatically set depending on your build configuration properties ("Debug" or "Release" mode). -The C# compiler compiles the code between the `#if` directive and `#endif` directive only if the specified symbol is defined, or not defined when the `!` not operator is used. Unlike C and C++, a numeric value to a symbol can't be assigned. The `#if` statement in C# is Boolean and only tests whether the symbol is defined or not. For example, the following code is compiled when `DEBUG` is defined: +The C# compiler compiles the code between the `#if` directive and `#endif` directive only if the specified symbol is defined, or not defined when the `!` not operator is used. Unlike C and C++, you can't assign a numeric value to a symbol. The `#if` statement in C# is Boolean and only tests whether the symbol is defined or not. For example, the following code is compiled when `DEBUG` is defined: ```csharp #if DEBUG @@ -116,7 +118,7 @@ The following code is compiled when `MYTEST` is **not** defined: #endif ``` -You can use the operators [`==` (equality)](operators/equality-operators.md#equality-operator-) and [`!=` (inequality)](operators/equality-operators.md#inequality-operator-) to test for the [`bool`](builtin-types/bool.md) values `true` or `false`. `true` means the symbol is defined. The statement `#if DEBUG` has the same meaning as `#if (DEBUG == true)`. You can use the [`&&` (and)](operators/boolean-logical-operators.md#conditional-logical-and-operator-), [`||` (or)](operators/boolean-logical-operators.md#conditional-logical-or-operator-), and [`!` (not)](operators/boolean-logical-operators.md#logical-negation-operator-) operators to evaluate whether multiple symbols are defined. You can also group symbols and operators with parentheses. +Use the operators [`==` (equality)](operators/equality-operators.md#equality-operator-) and [`!=` (inequality)](operators/equality-operators.md#inequality-operator-) to test for the [`bool`](builtin-types/bool.md) values `true` or `false`. `true` means the symbol is defined. The statement `#if DEBUG` has the same meaning as `#if (DEBUG == true)`. Use the [`&&` (and)](operators/boolean-logical-operators.md#conditional-logical-and-operator-), [`||` (or)](operators/boolean-logical-operators.md#conditional-logical-or-operator-), and [`!` (not)](operators/boolean-logical-operators.md#logical-negation-operator-) operators to evaluate whether multiple symbols are defined. You can also group symbols and operators with parentheses. The following example shows a complex directive that allows your code to take advantage of newer .NET features while remaining backward compatible. For example, imagine that you're using a NuGet package in your code, but the package only supports .NET 6 and up, as well as .NET Standard 2.0 and up: @@ -130,7 +132,7 @@ The following example shows a complex directive that allows your code to take ad `#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. Conditional compilation can be useful when compiling code for a debug build or when compiling for a specific configuration. -`#elif` lets you create a compound conditional directive. The `#elif` expression is evaluated if neither the preceding `#if` nor any preceding, optional, `#elif` directive expressions evaluate to `true`. If an `#elif` expression evaluates to `true`, the compiler evaluates all the code between the `#elif` and the next conditional directive. For example: +`#elif` lets you create a compound conditional directive. The compiler evaluates the `#elif` expression if neither the preceding `#if` nor any preceding, optional, `#elif` directive expressions evaluate to `true`. If an `#elif` expression evaluates to `true`, the compiler evaluates all the code between the `#elif` and the next conditional directive. For example: ```csharp #define VC7 @@ -142,11 +144,11 @@ The following example shows a complex directive that allows your code to take ad #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) must be the next preprocessor directive after `#else`. +`#else` lets you create a compound conditional directive. If none of the expressions in the preceding `#if` or (optional) `#elif` directives evaluate to `true`, the compiler evaluates all code between `#else` and the next `#endif`. `#endif` must be the next preprocessor directive after `#else`. `#endif` specifies the end of a conditional directive, which began with the `#if` directive. -The following example shows you how to define a `MYTEST` symbol on a file and then test the values of the `MYTEST` and `DEBUG` symbols. The output of this example depends on whether you built the project on **Debug** or **Release** configuration mode. +The following example shows how to define a `MYTEST` symbol in a file and then test the values of the `MYTEST` and `DEBUG` symbols. The output of this example depends on whether you built the project in **Debug** or **Release** configuration mode. ```csharp #define MYTEST @@ -168,7 +170,7 @@ public class MyClass } ``` -The following example shows you how to test for different target frameworks so you can use newer APIs when possible: +The following example shows how to test for different target frameworks so you can use newer APIs when possible: ```csharp public class MyClass @@ -187,12 +189,12 @@ public class MyClass ## Defining symbols -You use the following two preprocessor directives to define or undefine symbols for conditional compilation: +Use the following two preprocessor directives to define or undefine symbols for conditional compilation: - `#define`: Define a symbol. - `#undef`: Undefine a symbol. -You use `#define` to define a symbol. When you use the symbol as the expression passed to the `#if` directive, the expression evaluates to `true`, as the following example shows: +Use `#define` to define a symbol. When you use the symbol as the expression passed to the `#if` directive, the expression evaluates to `true`, as the following example shows: ```csharp #define VERBOSE @@ -203,13 +205,13 @@ You use `#define` to define a symbol. When you use the symbol as the expression ``` > [!NOTE] -> In C#, primitive constants should be defined using the [`const`](keywords/const.md) keyword. A `const` declaration creates a `static` member that can't be modified at runtime. The `#define` directive can't be used to declare constant values as is typically done in C and C++. If you have several such constants, consider creating a separate "Constants" class to hold them. +> In C#, primitive constants should be defined by using the [`const`](keywords/const.md) keyword. A `const` declaration creates a `static` member that can't be modified at runtime. The `#define` directive can't be used to declare constant values as is typically done in C and C++. If you have several such constants, consider creating a separate "Constants" class to hold them. -Symbols can be used to specify conditions for compilation. You can test for the symbol with either `#if` or `#elif`. You can also use the to perform conditional compilation. You can define a symbol, but you can't assign a value to a symbol. The `#define` directive must appear in the file before you use any instructions that aren't also preprocessor directives. You can also define a symbol with the [**DefineConstants**](compiler-options/language.md#defineconstants) compiler option. You can undefine a symbol with `#undef`. +Use symbols to specify conditions for compilation. Test for the symbol by using either `#if` or `#elif`. You can also use the to perform conditional compilation. You can define a symbol, but you can't assign a value to a symbol. The `#define` directive must appear in the file before you use any instructions that aren't also preprocessor directives. You can also define a symbol by using the [**DefineConstants**](compiler-options/language.md#defineconstants) compiler option. Undefine a symbol by using `#undef`. ## Defining regions -You can define regions of code that can be collapsed in an outline using the following two preprocessor directives: +Define regions of code that you can collapse in an outline by using the following two preprocessor directives: - `#region`: Start a region. - `#endregion`: End a region. @@ -231,13 +233,13 @@ A `#region` block must be terminated with an `#endregion` directive. A `#region` ## Error and warning information -You instruct the compiler to generate user-defined compiler errors and warnings, and control line information using the following directives: +You can use the following directives to generate user-defined compiler errors and warnings, and control line information: - `#error`: Generate a compiler error with a specified message. - `#warning`: Generate a compiler warning, with a specific message. - `#line`: Change the line number printed with compiler messages. -`#error` lets you generate a [CS1029](compiler-messages/preprocessor-errors.md) user-defined error from a specific location in your code. For example: +Use `#error` to generate a [CS1029](compiler-messages/preprocessor-errors.md) user-defined error from a specific location in your code. For example: ```csharp #error Deprecated code in this method. @@ -246,15 +248,15 @@ You instruct the compiler to generate user-defined compiler errors and warnings, > [!NOTE] > 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` lets you generate a [CS1030](compiler-messages/preprocessor-errors.md) level one compiler warning from a specific location in your code. For example: +Use `#warning` to generate a [CS1030](compiler-messages/preprocessor-errors.md) level one compiler warning from a specific location in your code. For example: ```csharp #warning Deprecated code in this method. ``` -`#line` lets you modify the compiler's line numbering and (optionally) the file name output for errors and warnings. +Use `#line` to 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. 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." The `#line default` directive returns the line numbering to its default numbering, which counts the lines renumbered by the previous directive. +The following example shows how to report two warnings associated with line numbers. 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 is reported as "Special." The `#line default` directive returns the line numbering to its default numbering, which counts the lines renumbered by the previous directive. ```csharp class MainClass @@ -285,9 +287,9 @@ 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 ``` -The `#line` directive might be used in an automated, intermediate step in the build process. 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`. +The `#line` directive might be used in an automated, intermediate step in the build process. For example, if you remove lines from the original source code file, but you still want the compiler to generate output based on the original line numbering in the file, you can remove lines and then simulate the original line numbering by using `#line`. -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. This option can also be used to allow ASP.NET to differentiate between user-defined and machine-generated code. Although ASP.NET is the primary consumer of this feature, it's likely that more source generators make use of it. +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) are stepped over. This option can also be used to allow ASP.NET to differentiate between user-defined and machine-generated code. Although ASP.NET is the primary consumer of this feature, it's likely that more source generators make use of it. 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 reports the current file name and line number of the error. @@ -302,18 +304,18 @@ You can use a new form of the `#line` directive: The components of this form are: -- `(1, 1)`: The start line and column for the first character on the line following the directive. In this example, the next line would be reported as line 1, column 1. +- `(1, 1)`: The start line and column for the first character on the line following the directive. In this example, the next line is reported as line 1, column 1. - `(5, 60)`: The end line and column for the marked region. -- `10`: The column offset for the `#line` directive to take effect. In this example, the 10th column would be reported as column one. The declaration `int b = 0;` begins at that column. This field is optional. If omitted, the directive takes effect on the first column. +- `10`: The column offset for the `#line` directive to take effect. In this example, the 10th column is reported as column one. The declaration `int b = 0;` begins at that column. This field is optional. If omitted, the directive takes effect on the first column. - `"partial-class.cs"`: The name of the output file. -The preceding example would generate the following warning: +The preceding example generates the following warning: ```dotnetcli partial-class.cs(1,5,1,6): warning CS0219: The variable 'b' is assigned but its value is never used ``` -After remapping, the variable, `b`, is on the first line, at character six, of the file `partial-class.cs`. +After remapping, the variable `b` is on the first line, at character six, of the file `partial-class.cs`. Domain-specific languages (DSLs) typically use this format to provide a better mapping from the source file to the generated C# output. The most common use of this extended `#line` directive is to remap warnings or errors that appear in a generated file to the original source. For example, consider this razor page: @@ -322,7 +324,7 @@ Domain-specific languages (DSLs) typically use this format to provide a better m Time: @DateTime.NowAndThen ``` -The property `DateTime.Now` was typed incorrectly as `DateTime.NowAndThen`. The generated C# for this razor snippet looks like the following, in `page.g.cs`: +The property `DateTime.Now` is typed incorrectly as `DateTime.NowAndThen`. The generated C# for this razor snippet looks like the following, in `page.g.cs`: ```csharp _builder.Add("Time: "); @@ -342,7 +344,7 @@ To see more examples of this format, see the [feature specification](~/_csharpla ## Pragmas -`#pragma` gives the compiler special instructions for the compilation of the file in which it appears. The compiler must support the pragmas you use. In other words, you can't use `#pragma` to create custom preprocessing instructions. +The compiler uses `#pragma` to get special instructions for compiling the file where it appears. The compiler must support the pragmas you use. In other words, you can't use `#pragma` to create custom preprocessing instructions. - [`#pragma warning`](#pragma-warning): Enable or disable warnings. - [`#pragma checksum`](#pragma-checksum): Generate a checksum. @@ -351,7 +353,7 @@ To see more examples of this format, see the [feature specification](~/_csharpla #pragma pragma-name pragma-arguments ``` -Where `pragma-name` is the name of a recognized pragma and `pragma-arguments` is the pragma-specific arguments. +`pragma-name` is the name of a recognized pragma. `pragma-arguments` is the pragma-specific arguments. ### #pragma warning @@ -362,12 +364,12 @@ Where `pragma-name` is the name of a recognized pragma and `pragma-arguments` is #pragma warning restore warning-list ``` -Where `warning-list` is a comma-separated list of warning numbers, such as `414, CS3021`. The "CS" prefix is optional. When no warning numbers are specified, `disable` disables all warnings and `restore` enables all warnings. +`warning-list` is a comma-separated list of warning numbers, such as `414, CS3021`. The "CS" prefix is optional. When you don't specify warning numbers, `disable` disables all warnings and `restore` enables all warnings. > [!NOTE] > To find warning numbers in Visual Studio, build your project and then look for the warning numbers in the **Output** window. -The `disable` takes effect beginning on the next line of the source file. The warning is restored on the line following the `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. +The `disable` takes effect beginning on the next line of the source file. The warning is restored on the line following the `restore`. If there's no `restore` in the file, the warnings restore to their default state at the first line of any later files in the same compilation. ```csharp // pragma_warning.cs @@ -404,15 +406,15 @@ Visual Studio format commands don't modify text in blocks of code where `disable ### #pragma checksum -Generates checksums for source files to aid with debugging ASP.NET pages. +Generates checksums for source files to help with debugging ASP.NET pages. ```csharp #pragma checksum "filename" "{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. +The directive uses `"filename"` as the name of the file to monitor for changes or updates, `"{guid}"` as the Globally Unique Identifier (GUID) for the hash algorithm, and `"checksum_bytes"` as the string of hexadecimal digits representing the bytes of the checksum. You must provide an even number of hexadecimal digits. An odd number of digits results in a compile-time warning, and the directive is ignored. -The Visual Studio debugger uses a checksum to make sure that it always finds the right source. The compiler computes the checksum for a source file, and then emits the output to the program database (PDB) file. The debugger then uses the PDB to compare against the checksum that it computes for the source file. +The Visual Studio debugger uses a checksum to make sure that it always finds the right source. The compiler computes the checksum for a source file, and then emits the output to the program database (PDB) file. The debugger uses the PDB to compare against the checksum that it computes for the source file. This solution doesn't work for ASP.NET projects, because the computed checksum is for the generated source file, rather than the .aspx file. To address this problem, `#pragma checksum` provides checksum support for ASP.NET pages. diff --git a/docs/csharp/language-reference/statements/checked-and-unchecked.md b/docs/csharp/language-reference/statements/checked-and-unchecked.md index a8f3ba6dae1d2..a0dfdf02ef5c3 100644 --- a/docs/csharp/language-reference/statements/checked-and-unchecked.md +++ b/docs/csharp/language-reference/statements/checked-and-unchecked.md @@ -1,7 +1,7 @@ --- title: "The checked and unchecked statements - overflow-checking" description: "Control the overflow-checking context. In a checked context, overflow causes an exception to be thrown. In an unchecked context, the result is truncated." -ms.date: 11/18/2025 +ms.date: 01/16/2026 f1_keywords: - "checked_CSharpKeyword" - "unchecked_CSharpKeyword" @@ -13,15 +13,17 @@ helpviewer_keywords: --- # The checked and unchecked statements (C# reference) -The `checked` and `unchecked` statements specify the overflow-checking context for integral-type arithmetic operations and conversions. The default statement is `unchecked`. When integer arithmetic overflow occurs, the overflow-checking context defines what happens. In a checked context, a is thrown; if overflow happens in a constant expression, a compile-time error occurs. In an unchecked context, the operation result is truncated by discarding any high-order bits that don't fit in the destination type. For example, addition wraps from the maximum value to the minimum value. The following example shows the same operation in both a checked and unchecked context: +The `checked` and `unchecked` statements specify the overflow-checking context for integral-type arithmetic operations and conversions. The default statement is `unchecked`. When integer arithmetic overflow occurs, the overflow-checking context defines what happens. In a checked context, a is thrown. If overflow happens in a constant expression, a compile-time error occurs. In an unchecked context, the operation result is truncated by discarding any high-order bits that don't fit in the destination type. For example, addition wraps from the maximum value to the minimum value. The following example shows the same operation in both a checked and unchecked context: :::code language="csharp" source="snippets/checked-and-unchecked/Program.cs" id="MainExample"::: > [!NOTE] -> The overflow behavior of *user-defined* operators and conversions can differ from the one described in the preceding paragraph. In particular, [user-defined checked operators](../operators/arithmetic-operators.md#user-defined-checked-operators) might not throw an exception in a checked context. +> The overflow behavior of *user-defined* operators and conversions can differ from the behavior described in the preceding paragraph. In particular, [user-defined checked operators](../operators/arithmetic-operators.md#user-defined-checked-operators) might not throw an exception in a checked context. For more information, see the [Arithmetic overflow and division by zero](../operators/arithmetic-operators.md#arithmetic-overflow-and-division-by-zero) and [User-defined checked operators](../operators/arithmetic-operators.md#user-defined-checked-operators) sections of the [Arithmetic operators](../operators/arithmetic-operators.md) article. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + To specify the overflow-checking context for an expression, you can also use the `checked` and `unchecked` operators, as the following example shows: :::code language="csharp" source="snippets/checked-and-unchecked/Program.cs" id="OperatorForm"::: @@ -30,7 +32,7 @@ The `checked` and `unchecked` statements and operators only affect the overflow- :::code language="csharp" source="snippets/checked-and-unchecked/Program.cs" id="ScopeExample"::: -At the preceding example, the first invocation of the `Multiply` local function shows that the `checked` statement doesn't affect the overflow-checking context within the `Multiply` function as no exception is thrown. At the second invocation of the `Multiply` function, the expression that calculates the second argument of the function is evaluated in a checked context and results in an exception as it's textually inside the block of the `checked` statement. +In the preceding example, the first invocation of the `Multiply` local function shows that the `checked` statement doesn't affect the overflow-checking context within the `Multiply` function as no exception is thrown. At the second invocation of the `Multiply` function, the expression that calculates the second argument of the function is evaluated in a checked context and results in an exception as it's textually inside the block of the `checked` statement. The behavior of `checked` and `unchecked` depends on the type and the operation. Even for integers, operations like `unchecked(x / 0)` always throw because there's no sensible behavior. Check the behavior for the type and the operation to understand how the `checked` and `unchecked` keywords affect your code. @@ -58,7 +60,7 @@ The overflow-checking context affects the following operations: If you don't specify the overflow-checking context, the value of the [**CheckForOverflowUnderflow**](../compiler-options/language.md#checkforoverflowunderflow) compiler option defines the default context for nonconstant expressions. By default the value of that option is unset and integral-type arithmetic operations and conversions are executed in an **unchecked** context. -Constant expressions are evaluated by default in a checked context and overflow causes a compile-time error. You can explicitly specify an unchecked context for a constant expression with the `unchecked` statement or operator. +Constant expressions are evaluated by default in a checked context and overflow causes a compile-time error. You can explicitly specify an unchecked context for a constant expression by using the `unchecked` statement or operator. ## C# language specification diff --git a/docs/csharp/language-reference/statements/declarations.md b/docs/csharp/language-reference/statements/declarations.md index 025ac3666099d..e224c9a5a9f99 100644 --- a/docs/csharp/language-reference/statements/declarations.md +++ b/docs/csharp/language-reference/statements/declarations.md @@ -1,7 +1,7 @@ --- title: "Declaration statements - local variables and constants, var, local reference variables (ref locals)" description: "Declaration statements introduce a new local variable, local constant, or local reference variable (ref local). Local variables can be explicitly or implicitly typed. A declaration statement can also include initialization of a variable's value." -ms.date: 06/21/2023 +ms.date: 01/16/2026 f1_keywords: - "var" - "var_CSharpKeyword" @@ -12,7 +12,11 @@ helpviewer_keywords: --- # Declaration statements -A declaration statement declares a new local variable, local constant, or [local reference variable](#reference-variables). To declare a local variable, specify its type and provide its name. You can declare multiple variables of the same type in one statement, as the following example shows: +A declaration statement declares a new local variable, local constant, or [local reference variable](#reference-variables). + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +To declare a local variable, specify its type and provide its name. You can declare multiple variables of the same type in one statement, as the following example shows: :::code language="csharp" source="snippets/declarations/Declaration.cs" id="Declare"::: @@ -30,18 +34,18 @@ When you declare a local constant, you must also initialize it. For information about local reference variables, see the [Reference variables](#reference-variables) section. -## Implicitly-typed local variables +## Implicitly typed local variables -When you declare a local variable, you can let the compiler infer the type of the variable from the initialization expression. To do that use the `var` keyword instead of the name of a type: +When you declare a local variable, you can let the compiler infer the type of the variable from the initialization expression. To do that, use the `var` keyword instead of the name of a type: :::code language="csharp" source="snippets/declarations/ImplicitlyTyped.cs" id="ImplicitlyTyped"::: -As the preceding example shows, implicitly-typed local variables are strongly typed. +As the preceding example shows, implicitly typed local variables are strongly typed. > [!NOTE] > When you use `var` in the enabled [nullable aware context](../builtin-types/nullable-reference-types.md) and the type of an initialization expression is a reference type, the compiler always infers a **nullable** reference type even if the type of an initialization expression isn't nullable. -A common use of `var` is with a [constructor invocation expression](../operators/new-operator.md#constructor-invocation). The use of `var` allows you to not repeat a type name in a variable declaration and object instantiation, as the following example shows: +A common use of `var` is with a [constructor invocation expression](../operators/new-operator.md#constructor-invocation). The use of `var` allows you to avoid repeating a type name in a variable declaration and object instantiation, as the following example shows: ```csharp var xs = new List(); @@ -54,13 +58,13 @@ List xs = new(); List? ys = new(); ``` -When you work with [anonymous types](../../fundamentals/types/anonymous-types.md), you must use implicitly-typed local variables. The following example shows a [query expression](../keywords/query-keywords.md) that uses an anonymous type to hold a customer's name and phone number: +When you work with [anonymous types](../../fundamentals/types/anonymous-types.md), you must use implicitly typed local variables. The following example shows a [query expression](../keywords/query-keywords.md) that uses an anonymous type to hold a customer's name and phone number: :::code language="csharp" source="snippets/declarations/ImplicitlyTyped.cs" id="VarExample"::: In the preceding example, you can't explicitly specify the type of the `fromPhoenix` variable. The type is but in this case `T` is an anonymous type and you can't provide its name. That's why you need to use `var`. For the same reason, you must use `var` when you declare the `customer` iteration variable in the `foreach` statement. -For more information about implicitly-typed local variables, see [Implicitly-typed local variables](../../programming-guide/classes-and-structs/implicitly-typed-local-variables.md). +For more information about implicitly typed local variables, see [Implicitly-typed local variables](../../programming-guide/classes-and-structs/implicitly-typed-local-variables.md). In pattern matching, the `var` keyword is used in a [`var` pattern](../operators/patterns.md#var-pattern). @@ -72,7 +76,7 @@ When you declare a local variable and add the `ref` keyword before the variable' ref int aliasOfvariable = ref variable; ``` -A reference variable is a variable that refers to another variable, which is called the *referent*. That is, a reference variable is an *alias* to its referent. When you assign a value to a reference variable, that value is assigned to the referent. When you read the value of a reference variable, the referent's value is returned. The following example demonstrates that behavior: +A reference variable is a variable that refers to another variable, which is called the *referent*. That is, a reference variable is an *alias* to its referent. When you assign a value to a reference variable, you assign that value to the referent. When you read the value of a reference variable, you return the referent's value. The following example demonstrates that behavior: :::code language="csharp" source="snippets/declarations/ReferenceVariables.cs" id="AliasToLocalVariable"::: @@ -82,7 +86,7 @@ Use the [`ref` assignment operator](../operators/assignment-operator.md#ref-assi In the preceding example, the `element` reference variable is initialized as an alias to the first array element. Then it's `ref` reassigned to refer to the last array element. -You can define a `ref readonly` local variable. You can't assign a value to a `ref readonly` variable. However you can `ref` reassign such a reference variable, as the following example shows: +You can define a `ref readonly` local variable. You can't assign a value to a `ref readonly` variable. However, you can `ref` reassign such a reference variable, as the following example shows: :::code language="csharp" source="snippets/declarations/ReferenceVariables.cs" id="RefReadonly"::: @@ -102,9 +106,9 @@ For information about the `ref` fields, see the [`ref` fields](../builtin-types/ ## scoped ref -The contextual keyword `scoped` restricts the lifetime of a value. The `scoped` modifier restricts the [*ref-safe-to-escape* or *safe-to-escape* lifetime](../keywords/method-parameters.md#safe-context-of-references-and-values), respectively, to the current method. Effectively, adding the `scoped` modifier asserts that your code won't extend the lifetime of the variable. +The contextual keyword `scoped` restricts the lifetime of a value. The `scoped` modifier restricts the [*ref-safe-to-escape* or *safe-to-escape* lifetime](../keywords/method-parameters.md#safe-context-of-references-and-values), respectively, to the current method. By adding the `scoped` modifier, you assert that your code doesn't extend the lifetime of the variable. -You can apply `scoped` to a parameter or local variable. The `scoped` modifier may be applied to parameters and locals when the type is a [`ref struct`](../builtin-types/ref-struct.md). Otherwise, the `scoped` modifier may be applied only to local [reference variables](#reference-variables). That includes local variables declared with the `ref` modifier and parameters declared with the `in`, `ref` or `out` modifiers. +Apply `scoped` to a parameter or local variable. You can apply the `scoped` modifier to parameters and locals when the type is a [`ref struct`](../builtin-types/ref-struct.md). Otherwise, apply the `scoped` modifier only to local [reference variables](#reference-variables). That rule includes local variables declared with the `ref` modifier and parameters declared with the `in`, `ref`, or `out` modifiers. The `scoped` modifier is implicitly added to `this` in methods declared in a `struct`, `out` parameters, and `ref` parameters when the type is a `ref struct`. diff --git a/docs/csharp/language-reference/statements/exception-handling-statements.md b/docs/csharp/language-reference/statements/exception-handling-statements.md index 5148bf610ec1c..fc8f338b73f89 100644 --- a/docs/csharp/language-reference/statements/exception-handling-statements.md +++ b/docs/csharp/language-reference/statements/exception-handling-statements.md @@ -1,7 +1,7 @@ --- title: "Exception-handling statements - throw and try, catch, finally" description: "Use the C# throw statement to signal an occurrence of an exception. Use the C# try statements to catch and process exceptions occurred in a block of code." -ms.date: 04/21/2023 +ms.date: 01/16/2026 f1_keywords: - "throw_CSharpKeyword" - "try_CSharpKeyword" @@ -23,7 +23,9 @@ helpviewer_keywords: --- # Exception-handling statements - `throw`, `try-catch`, `try-finally`, and `try-catch-finally` -You use the `throw` and `try` statements to work with exceptions. Use the [`throw` statement](#the-throw-statement) to throw an exception. Use the [`try` statement](#the-try-statement) to catch and handle exceptions that might occur during execution of a code block. +Use the `throw` and `try` statements to work with exceptions. Use the [`throw` statement](#the-throw-statement) to throw an exception. Use the [`try` statement](#the-try-statement) to catch and handle exceptions that might occur during execution of a code block. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] ## The `throw` statement @@ -33,20 +35,20 @@ The `throw` statement throws an exception: In a `throw e;` statement, the result of expression `e` must be implicitly convertible to . -You can use the built-in exception classes, for example, or . .NET also provides the following helper methods to throw exceptions in certain conditions: and . You can also define your own exception classes that derive from . For more information, see [Creating and throwing exceptions](../../fundamentals/exceptions/creating-and-throwing-exceptions.md). +You can use the built-in exception classes, such as or . .NET also provides the following helper methods to throw exceptions in certain conditions: and . You can also define your own exception classes that derive from . For more information, see [Creating and throwing exceptions](../../fundamentals/exceptions/creating-and-throwing-exceptions.md). -Inside a [`catch` block](#the-try-catch-statement), you can use a `throw;` statement to re-throw the exception that is handled by the `catch` block: +Inside a [`catch` block](#the-try-catch-statement), use a `throw;` statement to re-throw the exception that the `catch` block handles: :::code language="csharp" source="snippets/exception-handling-statements/Program.cs" id="Rethrow"::: > [!NOTE] -> `throw;` preserves the original stack trace of the exception, which is stored in the property. Opposite to that, `throw e;` updates the property of `e`. +> `throw;` preserves the original stack trace of the exception, which is stored in the property. In contrast, `throw e;` updates the property of `e`. -When an exception is thrown, the common language runtime (CLR) looks for the [`catch` block](#the-try-catch-statement) that can handle this exception. If the currently executed method doesn't contain such a `catch` block, the CLR looks at the method that called the current method, and so on up the call stack. If no `catch` block is found, the CLR terminates the executing thread. For more information, see the [How exceptions are handled](~/_csharpstandard/standard/exceptions.md#224-how-exceptions-are-handled) section of the [C# language specification](~/_csharpstandard/standard/README.md). +When an exception is thrown, the common language runtime (CLR) looks for the [`catch` block](#the-try-catch-statement) that can handle this exception. If the currently executed method doesn't contain such a `catch` block, the CLR looks at the method that called the current method, and so on up the call stack. If there's no compatible `catch` block, the CLR terminates the executing thread. For more information, see the [How exceptions are handled](~/_csharpstandard/standard/exceptions.md#224-how-exceptions-are-handled) section of the [C# language specification](~/_csharpstandard/standard/README.md). ### The `throw` expression -You can also use `throw` as an expression. This might be convenient in a number of cases, which include: +You can also use `throw` as an expression. This approach might be convenient in several cases, including: - [the conditional operator](../operators/conditional-operator.md). The following example uses a `throw` expression to throw an when the passed array `args` is empty: @@ -56,13 +58,13 @@ You can also use `throw` as an expression. This might be convenient in a number :::code language="csharp" source="snippets/exception-handling-statements/ExampleClass.cs" id="ThrowExpressionCoalescing"::: -- an expression-bodied [lambda](../operators/lambda-expressions.md) or method. The following example uses a `throw` expression to throw an to indicate that a conversion to a value is not supported: +- an expression-bodied [lambda](../operators/lambda-expressions.md) or method. The following example uses a `throw` expression to throw an to indicate that a conversion to a value isn't supported: :::code language="csharp" source="snippets/exception-handling-statements/Program.cs" id="ThrowExpressionExpressionBody"::: ## The `try` statement -You can use the `try` statement in any of the following forms: [`try-catch`](#the-try-catch-statement) - to handle exceptions that might occur during execution of the code inside a `try` block, [`try-finally`](#the-try-finally-statement) - to specify the code that is executed when control leaves the `try` block, and [`try-catch-finally`](#the-try-catch-finally-statement) - as a combination of the preceding two forms. +You can use the `try` statement in any of the following forms: [`try-catch`](#the-try-catch-statement) - to handle exceptions that might occur during execution of the code inside a `try` block, [`try-finally`](#the-try-finally-statement) - to specify the code that runs when control leaves the `try` block, and [`try-catch-finally`](#the-try-catch-finally-statement) - as a combination of the preceding two forms. ### The `try-catch` statement @@ -74,14 +76,14 @@ You can provide several catch clauses: :::code language="csharp" source="snippets/exception-handling-statements/Program.cs" id="TryMultipleCatch"::: -When an exception occurs, catch clauses are examined in the specified order, from top to bottom. At maximum, only one `catch` block is executed for any thrown exception. As the preceding example also shows, you can omit declaration of an exception variable and specify only the exception type in a catch clause. A catch clause without any specified exception type matches any exception and, if present, must be the last catch clause. +When an exception occurs, the runtime checks catch clauses in the specified order, from top to bottom. At most, only one `catch` block runs for any thrown exception. As the preceding example also shows, you can omit declaration of an exception variable and specify only the exception type in a catch clause. A catch clause without any specified exception type matches any exception and, if present, must be the last catch clause. -If you want to re-throw a caught exception, use the [`throw` statement](#the-throw-statement), as the following example shows: +To re-throw a caught exception, use the [`throw` statement](#the-throw-statement), as the following example shows: :::code language="csharp" source="snippets/exception-handling-statements/Program.cs" id="RethrowInCatch"::: > [!NOTE] -> `throw;` preserves the original stack trace of the exception, which is stored in the property. Opposite to that, `throw e;` updates the property of `e`. +> `throw;` preserves the original stack trace of the exception, which is stored in the property. In contrast, `throw e;` updates the property of `e`. #### A `when` exception filter @@ -100,7 +102,7 @@ If a `catch` clause has an exception filter, it can specify the exception type t Exception filters provide significant advantages over traditional exception handling approaches. The key difference is **when** the exception handling logic is evaluated: - **Exception filters (`when`)**: The filter expression is evaluated *before* the stack is unwound. This means the original call stack and all local variables remain intact during filter evaluation. -- **Traditional `catch` blocks**: The catch block executes *after* the stack is unwound, potentially losing valuable debugging information. +- **Traditional `catch` blocks**: The catch block runs *after* the stack is unwound, potentially losing valuable debugging information. Here's a comparison showing the difference: @@ -128,21 +130,21 @@ Use exception filters when you need to: ### Stack trace preservation -Exception filters preserve the original `ex.StackTrace` property. If a `catch` clause can't process the exception and re-throws, the original stack information is lost. The `when` filter doesn't unwind the stack, so if a `when` filter is `false`, the original stack trace isn't changed. +Exception filters preserve the original `ex.StackTrace` property. If a `catch` clause can't process the exception and re-throws it, the original stack information is lost. The `when` filter doesn't unwind the stack, so if a `when` filter is `false`, the original stack trace isn't changed. -The exception filter approach is valuable in applications where preserving debugging information is crucial for diagnosing issues. +The exception filter approach is valuable in applications where preserving debugging information is crucial for diagnosing code errors. #### Exceptions in async and iterator methods -If an exception occurs in an [async function](../keywords/async.md), it propagates to the caller of the function when you [await](../operators/await.md) the result of the function, as the following example shows: +If an exception occurs in an [async function](../keywords/async.md), the exception propagates to the caller of the function when you [await](../operators/await.md) the result of the function, as the following example shows: :::code language="csharp" source="snippets/exception-handling-statements/ExceptionFromAsyncExample.cs" id="ExceptionFromAsync"::: -If an exception occurs in an [iterator method](../../iterators.md), it propagates to the caller only when the iterator advances to the next element. +If an exception occurs in an [iterator method](../../iterators.md), the exception propagates to the caller only when the iterator advances to the next element. ### The `try-finally` statement -In a `try-finally` statement, the `finally` block is executed when control leaves the `try` block. Control might leave the `try` block as a result of +In a `try-finally` statement, the `finally` block runs when control leaves the `try` block. Control might leave the `try` block as a result of - normal execution, - execution of a [jump statement](jump-statements.md) (that is, `return`, `break`, `continue`, or `goto`), or @@ -157,15 +159,15 @@ You can also use the `finally` block to clean up allocated resources used in the > [!NOTE] > When the type of a resource implements the or interface, consider the [`using` statement](using.md). The `using` statement ensures that acquired resources are disposed when control leaves the `using` statement. The compiler transforms a `using` statement into a `try-finally` statement. -Execution of the `finally` block depends on whether the operating system chooses to trigger an exception unwind operation. The only cases where `finally` blocks aren't executed involve immediate termination of a program. For example, such a termination might happen because of the call or an or exception. Most operating systems perform a reasonable resource clean-up as part of stopping and unloading the process. +Whether the `finally` block executes depends on whether the operating system chooses to trigger an exception unwind operation. The only cases where `finally` blocks don't execute involve immediate termination of a program. For example, such a termination might happen because of the call or an or exception. Most operating systems perform reasonable resource clean-up as part of stopping and unloading the process. ### The `try-catch-finally` statement -You use a `try-catch-finally` statement both to handle exceptions that might occur during execution of the `try` block and specify the code that must be executed when control leaves the `try` statement: +Use a `try-catch-finally` statement both to handle exceptions that might occur during execution of the `try` block and to specify the code that must run when control leaves the `try` statement: :::code language="csharp" source="snippets/exception-handling-statements/ExampleClass.cs" id="TryCatchFinally"::: -When an exception is handled by a `catch` block, the `finally` block is executed after execution of that `catch` block (even if another exception occurs during execution of the `catch` block). For information about `catch` and `finally` blocks, see [The `try-catch` statement](#the-try-catch-statement) and [The `try-finally` statement](#the-try-finally-statement) sections, respectively. +When a `catch` block handles an exception, the `finally` block runs after the `catch` block finishes (even if another exception occurs during execution of the `catch` block). For information about `catch` and `finally` blocks, see [The `try-catch` statement](#the-try-catch-statement) and [The `try-finally` statement](#the-try-finally-statement) sections, respectively. ## C# language specification diff --git a/docs/csharp/language-reference/statements/fixed.md b/docs/csharp/language-reference/statements/fixed.md index 569534311728b..cac7fa0c4b576 100644 --- a/docs/csharp/language-reference/statements/fixed.md +++ b/docs/csharp/language-reference/statements/fixed.md @@ -1,7 +1,7 @@ --- title: "fixed statement - pin a moveable variable" description: "Use the C# `fixed` statement to pin a moveable variable and declare a pointer to that variable. The address of a pinned variable doesn't change during execution of the statement." -ms.date: 11/22/2022 +ms.date: 01/16/2026 f1_keywords: - "fixed_CSharpKeyword" - "fixed" @@ -15,8 +15,10 @@ The `fixed` statement prevents the [garbage collector](../../../standard/garbage :::code language="csharp" source="snippets/fixed/Program.cs" id="PinnedArray"::: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + > [!NOTE] -> You can use the `fixed` statement only in an [unsafe](../keywords/unsafe.md) context. The code that contains unsafe blocks must be compiled with the [**AllowUnsafeBlocks**](../compiler-options/language.md#allowunsafeblocks) compiler option. +> You can use the `fixed` statement only in an [unsafe](../keywords/unsafe.md) context. The code that contains unsafe blocks must be compiled by using the [**AllowUnsafeBlocks**](../compiler-options/language.md#allowunsafeblocks) compiler option. You can initialize the declared pointer as follows: @@ -25,7 +27,7 @@ You can initialize the declared pointer as follows: :::code language="csharp" source="snippets/fixed/Program.cs" id="PinnedVariable"::: - Object fields are another example of moveable variables that can be pinned. + Object fields are another example of moveable variables that you can pin. When the initialized pointer contains the address of an object field or an array element, the `fixed` statement guarantees that the garbage collector doesn't relocate or dispose of the containing object instance during the execution of the statement body. diff --git a/docs/csharp/language-reference/statements/iteration-statements.md b/docs/csharp/language-reference/statements/iteration-statements.md index eac8c14d1f5b8..bbe8e7f39f1b8 100644 --- a/docs/csharp/language-reference/statements/iteration-statements.md +++ b/docs/csharp/language-reference/statements/iteration-statements.md @@ -1,7 +1,7 @@ --- title: "Iteration statements -for, foreach, do, and while" description: "C# iteration statements (for, foreach, do, and while) repeatedly execute a block of code. You use those statements to create loops or iterate through a collection." -ms.date: 11/22/2022 +ms.date: 01/16/2026 f1_keywords: - "for_CSharpKeyword" - "foreach_CSharpKeyword" @@ -20,9 +20,11 @@ helpviewer_keywords: --- # Iteration statements - `for`, `foreach`, `do`, and `while` -The iteration statements repeatedly execute a statement or a block of statements. The [`for` statement](#the-for-statement) executes its body while a specified Boolean expression evaluates to `true`. The [`foreach` statement](#the-foreach-statement) enumerates the elements of a collection and executes its body for each element of the collection. The [`do` statement](#the-do-statement) conditionally executes its body one or more times. The [`while` statement](#the-while-statement) conditionally executes its body zero or more times. +Use iteration statements to repeatedly execute a statement or a block of statements. The [`for` statement](#the-for-statement) executes its body while a specified Boolean expression evaluates to `true`. The [`foreach` statement](#the-foreach-statement) enumerates the elements of a collection and executes its body for each element of the collection. The [`do` statement](#the-do-statement) conditionally executes its body one or more times. The [`while` statement](#the-while-statement) conditionally executes its body zero or more times. -At any point within the body of an iteration statement, you can break out of the loop using the [`break` statement](jump-statements.md#the-break-statement). You can step to the next iteration in the loop using the [`continue` statement](jump-statements.md#the-continue-statement). +At any point within the body of an iteration statement, you can exit the loop by using the [`break` statement](jump-statements.md#the-break-statement). You can step to the next iteration in the loop by using the [`continue` statement](jump-statements.md#the-continue-statement). + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] ## The `for` statement @@ -32,7 +34,7 @@ The `for` statement executes a statement or a block of statements while a specif The preceding example shows the elements of the `for` statement: -- The *initializer* section that is executed only once, before entering the loop. Typically, you declare and initialize a local loop variable in that section. The declared variable can't be accessed from outside the `for` statement. +- The *initializer* section that executes only once, before entering the loop. Typically, you declare and initialize a local loop variable in that section. You can't access the declared variable from outside the `for` statement. The *initializer* section in the preceding example declares and initializes an integer counter variable: @@ -40,7 +42,7 @@ The preceding example shows the elements of the `for` statement: int i = 0 ``` -- The *condition* section that determines if the next iteration in the loop should be executed. If it evaluates to `true` or isn't present, the next iteration is executed; otherwise, the loop is exited. The *condition* section must be a Boolean expression. +- The *condition* section that determines if the next iteration in the loop should run. If it evaluates to `true` or isn't present, the next iteration runs. Otherwise, the loop exits. The *condition* section must be a Boolean expression. The *condition* section in the preceding example checks if a counter value is less than three: @@ -94,31 +96,31 @@ If the enumerator's `Current` property returns a [reference return value](jump-s :::code language="csharp" source="snippets/iteration-statements/ForeachStatement.cs" id="RefIterationVariable" ::: -If the source collection of the `foreach` statement is empty, the body of the `foreach` statement isn't executed and skipped. If the `foreach` statement is applied to `null`, a is thrown. +If the source collection of the `foreach` statement is empty, the `foreach` statement's body isn't executed and skipped. If the `foreach` statement is applied to `null`, a is thrown. ### await foreach -You can use the `await foreach` statement to consume an asynchronous stream of data, that is, the collection type that implements the interface. Each iteration of the loop can be suspended while the next element is retrieved asynchronously. The following example shows how to use the `await foreach` statement: +Use the `await foreach` statement to consume an asynchronous stream of data, that is, a collection type that implements the interface. Each iteration of the loop can suspend while the next element is retrieved asynchronously. The following example shows how to use the `await foreach` statement: :::code language="csharp" source="snippets/iteration-statements/ForeachStatement.cs" id="AwaitForeach" ::: You can also use the `await foreach` statement with an instance of any type that satisfies the following conditions: -- A type has the public parameterless `GetAsyncEnumerator` method. That method can be an [extension member](../../programming-guide/classes-and-structs/extension-methods.md). +- A type has the public parameterless `GetAsyncEnumerator` method. This method can be an [extension member](../../programming-guide/classes-and-structs/extension-methods.md). - The return type of the `GetAsyncEnumerator` method has the public `Current` property and the public parameterless `MoveNextAsync` method whose return type is [`Task`](xref:System.Threading.Tasks.Task%601), [`ValueTask`](xref:System.Threading.Tasks.ValueTask%601), or any other awaitable type whose awaiter's `GetResult` method returns a `bool` value. -By default, stream elements are processed in the captured context. If you want to disable capturing of the context, use the extension method. For more information about synchronization contexts and capturing the current context, see [Consuming the Task-based asynchronous pattern](../../../standard/asynchronous-programming-patterns/consuming-the-task-based-asynchronous-pattern.md). For more information about asynchronous streams, see the [Asynchronous streams tutorial](../../asynchronous-programming/generate-consume-asynchronous-stream.md). +By default, the `await foreach` statement processes stream elements in the captured context. If you want to disable capturing of the context, use the extension method. For more information about synchronization contexts and capturing the current context, see [Consuming the Task-based asynchronous pattern](../../../standard/asynchronous-programming-patterns/consuming-the-task-based-asynchronous-pattern.md). For more information about asynchronous streams, see the [Asynchronous streams tutorial](../../asynchronous-programming/generate-consume-asynchronous-stream.md). ### Type of an iteration variable -You can use the [`var` keyword](declarations.md#implicitly-typed-local-variables) to let the compiler infer the type of an iteration variable in the `foreach` statement, as the following code shows: +Use the [`var` keyword](declarations.md#implicitly-typed-local-variables) to let the compiler infer the type of an iteration variable in the `foreach` statement, as the following code shows: ```csharp foreach (var item in collection) { } ``` > [!NOTE] -> The type of a `var` declaration can be inferred by the compiler as a nullable reference type, depending on whether the [nullable aware context](../../language-reference/builtin-types/nullable-reference-types.md) is enabled and whether the type of an initialization expression is a reference type. +> The compiler can infer the type of a `var` declaration as a nullable reference type, depending on whether the [nullable aware context](../../language-reference/builtin-types/nullable-reference-types.md) is enabled and whether the type of an initialization expression is a reference type. > For more information, see [Implicitly-typed local variables](./declarations.md#implicitly-typed-local-variables). You can also explicitly specify the type of an iteration variable, as the following code shows: @@ -132,7 +134,7 @@ In the preceding form, type `T` of a collection element must be implicitly or ex ## The `do` statement -The `do` statement executes a statement or a block of statements while a specified Boolean expression evaluates to `true`. Because that expression is evaluated after each execution of the loop, a `do` loop executes one or more times. The `do` loop differs from the [`while` loop](#the-while-statement), which executes zero or more times. +The `do` statement executes a statement or a block of statements while a specified Boolean expression evaluates to `true`. Because the loop evaluates that expression after each execution, a `do` loop executes one or more times. The `do` loop differs from the [`while` loop](#the-while-statement), which executes zero or more times. The following example shows the usage of the `do` statement: @@ -140,7 +142,7 @@ The following example shows the usage of the `do` statement: ## The `while` statement -The `while` statement executes a statement or a block of statements while a specified Boolean expression evaluates to `true`. Because that expression is evaluated before each execution of the loop, a `while` loop executes zero or more times. The `while` loop differs from the [`do` loop](#the-do-statement), which executes one or more times. +The `while` statement executes a statement or a block of statements while a specified Boolean expression evaluates to `true`. Because the loop evaluates that expression before each execution, a `while` loop executes zero or more times. The `while` loop differs from the [`do` loop](#the-do-statement), which executes one or more times. The following example shows the usage of the `while` statement: diff --git a/docs/csharp/language-reference/statements/jump-statements.md b/docs/csharp/language-reference/statements/jump-statements.md index 2344db84b959b..4aedc80771753 100644 --- a/docs/csharp/language-reference/statements/jump-statements.md +++ b/docs/csharp/language-reference/statements/jump-statements.md @@ -1,7 +1,7 @@ --- title: "Jump statements - break, continue, return, and goto" description: "C# jump statements (break, continue, return, and goto) unconditionally transfer control from the current location to a different statement." -ms.date: 11/22/2022 +ms.date: 01/16/2026 f1_keywords: - "break_CSharpKeyword" - "continue_CSharpKeyword" @@ -23,6 +23,8 @@ The jump statements unconditionally transfer control. The [`break` statement](#t For information about the `throw` statement that throws an exception and unconditionally transfers control as well, see [The `throw` statement](exception-handling-statements.md#the-throw-statement) section of the [Exception-handling statements](exception-handling-statements.md) article. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + ## The `break` statement The `break` statement terminates the closest enclosing [iteration statement](iteration-statements.md) (that is, `for`, `foreach`, `while`, or `do` loop) or [`switch` statement](selection-statements.md#the-switch-statement). The `break` statement transfers control to the statement that follows the terminated statement, if any. @@ -45,19 +47,19 @@ The `continue` statement starts a new iteration of the closest enclosing [iterat ## The `return` statement -The `return` statement terminates execution of the function in which it appears and returns control and the function's result, if any, to the caller. +The `return` statement terminates execution of the function where it appears. It returns control and the function's result, if any, to the caller. -If a function member doesn't compute a value, you use the `return` statement without expression, as the following example shows: +If a function member doesn't compute a value, use the `return` statement without an expression, as the following example shows: :::code language="csharp" source="snippets/jump-statements/ReturnStatement.cs" id="WithoutExpression"::: -As the preceding example shows, you typically use the `return` statement without expression to terminate a function member early. If a function member doesn't contain the `return` statement, it terminates after its last statement is executed. +As the preceding example shows, typically use the `return` statement without an expression to terminate a function member early. If a function member doesn't contain the `return` statement, it terminates after its last statement executes. -If a function member computes a value, you use the `return` statement with an expression, as the following example shows: +If a function member computes a value, use the `return` statement with an expression, as the following example shows: :::code language="csharp" source="snippets/jump-statements/ReturnStatement.cs" id="WithExpression"::: -When the `return` statement has an expression, that expression must be implicitly convertible to the return type of a function member unless it's [async](../keywords/async.md). The expression returned from an `async` function must be implicitly convertible to the type argument of or , whichever is the return type of the function. If the return type of an `async` function is or , you use the `return` statement without expression. +When the `return` statement has an expression, that expression must be implicitly convertible to the return type of a function member unless it's [async](../keywords/async.md). The expression returned from an `async` function must be implicitly convertible to the type argument of or , whichever is the return type of the function. If the return type of an `async` function is or , use the `return` statement without expression. ### Ref returns @@ -106,7 +108,7 @@ Here's a more complete ref return example, showing both the method signature and :::code language="csharp" source="snippets/jump-statements/RefParameterModifier.cs" id="SnippetFindReturningRef"::: -The called method may also declare the return value as `ref readonly` to return the value by reference, and enforce that the calling code can't modify the returned value. The calling method can avoid copying the returned value by storing the value in a local `ref readonly` reference variable. +The called method can also declare the return value as `ref readonly` to return the value by reference and enforce that the calling code can't modify the returned value. The calling method can avoid copying the returned value by storing the value in a local `ref readonly` reference variable. The following example defines a `Book` class that has two fields, `Title` and `Author`. It also defines a `BookCollection` class that includes a private array of `Book` objects. Individual book objects are returned by reference by calling its `GetBookByTitle` method. @@ -118,14 +120,14 @@ When the caller stores the value returned by the `GetBookByTitle` method as a re ## The `goto` statement -The `goto` statement transfers control to a statement that is marked by a label, as the following example shows: +The `goto` statement transfers control to a statement that a label marks, as the following example shows: :::code language="csharp" source="snippets/jump-statements/GotoStatement.cs" id="NestedLoops"::: -As the preceding example shows, you can use the `goto` statement to get out of a nested loop. +As the preceding example shows, you can use the `goto` statement to exit a nested loop. > [!TIP] -> When you work with nested loops, consider refactoring separate loops into separate methods. That may lead to a simpler, more readable code without the `goto` statement. +> When you work with nested loops, consider refactoring separate loops into separate methods. That approach can lead to simpler, more readable code without the `goto` statement. You can also use the `goto` statement in the [`switch` statement](selection-statements.md#the-switch-statement) to transfer control to a switch section with a constant case label, as the following example shows: @@ -133,7 +135,7 @@ You can also use the `goto` statement in the [`switch` statement](selection-stat Within the `switch` statement, you can also use the statement `goto default;` to transfer control to the switch section with the `default` label. -If a label with the given name doesn't exist in the current function member, or if the `goto` statement isn't within the scope of the label, a compile-time error occurs. That is, you can't use the `goto` statement to transfer control out of the current function member or into any nested scope. +If a label with the given name doesn't exist in the current function member, or if the `goto` statement isn't within the scope of the label, a compile-time error occurs. You can't use the `goto` statement to transfer control out of the current function member or into any nested scope. ## C# language specification diff --git a/docs/csharp/language-reference/statements/lock.md b/docs/csharp/language-reference/statements/lock.md index 6d393e9e743ba..97e82b2e204d5 100644 --- a/docs/csharp/language-reference/statements/lock.md +++ b/docs/csharp/language-reference/statements/lock.md @@ -1,7 +1,7 @@ --- title: "The lock statement - synchronize access to shared resources" description: "Use the C# lock statement to ensure that only a single thread exclusively reads or writes a shared resource, blocking all other threads until it completes." -ms.date: 05/02/2024 +ms.date: 01/16/2026 f1_keywords: - "lock_CSharpKeyword" - "lock" @@ -10,7 +10,9 @@ helpviewer_keywords: --- # The lock statement - ensure exclusive access to a shared resource -The `lock` statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released. The `lock` statement ensures that at maximum only one thread executes its body at any moment in time. +The `lock` statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can acquire and release the lock multiple times. Any other thread is blocked from acquiring the lock and waits until the lock is released. The `lock` statement ensures that at most only one thread executes its body at any moment in time. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] The `lock` statement takes the following form: @@ -21,7 +23,7 @@ lock (x) } ``` -The variable `x` is an expression of type, or a [reference type](../keywords/reference-types.md). When `x` is known at compile-time to be of the type , it's precisely equivalent to: +The variable `x` is an expression of type, or a [reference type](../keywords/reference-types.md). When the compiler knows that `x` is of the type , it's precisely equivalent to: ```csharp using (x.EnterScope()) @@ -30,7 +32,7 @@ using (x.EnterScope()) } ``` -The object returned by is a [`ref struct`](../builtin-types/ref-struct.md) that includes a `Dispose()` method. The generated [`using`](using.md) statement ensures the scope is released even if an exception is thrown with the body of the `lock` statement. +The object returned by is a [`ref struct`](../builtin-types/ref-struct.md) that includes a `Dispose()` method. The generated [`using`](using.md) statement ensures the scope is released even if an exception is thrown within the body of the `lock` statement. Otherwise, the `lock` statement is precisely equivalent to: @@ -54,7 +56,7 @@ You can't use the [`await` expression](../operators/await.md) in the body of a ` ## Guidelines -Beginning with .NET 9 and C# 13, lock a dedicated object instance of the type for best performance. In addition, the compiler issues a warning if a known `Lock` object is cast to another type and locked. If using an older version of .NET and C#, lock on a dedicated object instance that isn't used for another purpose. Avoid using the same lock object instance for different shared resources, as it might result in deadlock or lock contention. In particular, avoid using the following instances as lock objects: +Starting with .NET 9 and C# 13, lock a dedicated object instance of the type for best performance. The compiler also issues a warning if you cast a known `Lock` object to another type and lock it. If you're using an older version of .NET and C#, lock on a dedicated object instance that isn't used for another purpose. Avoid using the same lock object instance for different shared resources, as it might result in deadlock or lock contention. In particular, avoid using the following instances as lock objects: - `this`, as callers might also lock `this`. - instances, as they might be obtained by the [typeof](../operators/type-testing-and-cast.md#the-typeof-operator) operator or reflection. diff --git a/docs/csharp/language-reference/statements/selection-statements.md b/docs/csharp/language-reference/statements/selection-statements.md index 9b6ec2b4e8795..db4e1b4ba1869 100644 --- a/docs/csharp/language-reference/statements/selection-statements.md +++ b/docs/csharp/language-reference/statements/selection-statements.md @@ -1,7 +1,7 @@ --- title: "if and switch statements - select a code path to execute" description: "The `if` and `switch` statements provide branching logic in C#. You use `if, `else` and `switch` to choose the path your program follows." -ms.date: 11/22/2022 +ms.date: 01/16/2026 f1_keywords: - "if_CSharpKeyword" - "else_CSharpKeyword" @@ -19,7 +19,9 @@ helpviewer_keywords: --- # Selection statements - `if`, `if-else`, and `switch` -The `if`, `if-else` and `switch` statements select statements to execute from many possible paths based on the value of an expression. The [`if` statement](#the-if-statement) executes a statement only if a provided Boolean expression evaluates to `true`. The [`if-else` statement](#the-if-statement) allows you to choose which of the two code paths to follow based on a Boolean expression. The [`switch` statement](#the-switch-statement) selects a statement list to execute based on a pattern match with an expression. +The `if`, `if-else`, and `switch` statements select statements to execute from many possible paths based on the value of an expression. The [`if` statement](#the-if-statement) executes a statement only if a provided Boolean expression evaluates to `true`. The [`if-else` statement](#the-if-statement) lets you choose which of the two code paths to follow based on a Boolean expression. The [`switch` statement](#the-switch-statement) selects a statement list to execute based on a pattern match with an expression. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] ## The `if` statement @@ -37,15 +39,15 @@ You can nest `if` statements to check multiple conditions, as the following exam :::code language="csharp" source="snippets/selection-statements/IfStatement.cs" id="NestedIf"::: -In an expression context, you can use the [conditional operator `?:`](../operators/conditional-operator.md) to evaluate one of the two expressions based on the value of a Boolean expression. +In an expression context, use the [conditional operator `?:`](../operators/conditional-operator.md) to evaluate one of the two expressions based on the value of a Boolean expression. ## The `switch` statement -The `switch` statement selects a statement list to execute based on a pattern match with a match expression, as the following example shows: +The `switch` statement selects a series of statements to execute based on a pattern match with a match expression, as the following example shows: :::code language="csharp" source="snippets/selection-statements/SwitchStatement.cs" id="Example"::: -At the preceding example, the `switch` statement uses the following patterns: +In the preceding example, the `switch` statement uses the following patterns: - A [relational pattern](../operators/patterns.md#relational-patterns): to compare an expression result with a constant. - A [constant pattern](../operators/patterns.md#constant-pattern): test if an expression result equals a constant. @@ -55,7 +57,7 @@ At the preceding example, the `switch` statement uses the following patterns: The preceding example also demonstrates the `default` case. The `default` case specifies statements to execute when a match expression doesn't match any other case pattern. If a match expression doesn't match any case pattern and there's no `default` case, control falls through a `switch` statement. -A `switch` statement executes the *statement list* in the first *switch section* whose *case pattern* matches a match expression and whose [case guard](#case-guards), if present, evaluates to `true`. A `switch` statement evaluates case patterns in text order from top to bottom. The compiler generates an error when a `switch` statement contains an unreachable case. That is a case that is already handled by an upper case or whose pattern is impossible to match. +A `switch` statement executes the *statement list* in the first *switch section* whose *case pattern* matches a match expression and whose [case guard](#case-guards), if present, evaluates to `true`. A `switch` statement evaluates case patterns in text order from top to bottom. The compiler generates an error when a `switch` statement contains an unreachable case. That error occurs when an upper case already handles the case or when the pattern is impossible to match. > [!NOTE] > The `default` case can appear in any place within a `switch` statement. Regardless of its position, the `default` case is evaluated only if all other case patterns aren't matched or the `goto default;` statement is executed in one of the switch sections. @@ -67,7 +69,7 @@ You can specify multiple case patterns for one section of a `switch` statement, Within a `switch` statement, control can't fall through from one switch section to the next. As the examples in this section show, typically you use the `break` statement at the end of each switch section to pass control out of a `switch` statement. You can also use the [return](jump-statements.md#the-return-statement) and [throw](exception-handling-statements.md#the-throw-statement) statements to pass control out of a `switch` statement. To imitate the fall-through behavior and pass control to other switch section, you can use the [`goto` statement](jump-statements.md#the-goto-statement). > [!IMPORTANT] -> Every *switch section* must end with a `break`, `goto` or `return`. Falling through from one switch section to the next generates a compiler error. However, multiple switch labels can be applied to the same switch section, like `case < 0:` in example above. This deliberate design choice allows for concisely handling multiple cases that share the same or interdependent logic. +> Every *switch section* must end with a `break`, `goto`, or `return`. Falling through from one switch section to the next generates a compiler error. However, you can apply multiple switch labels to the same switch section, like `case < 0:` in the preceding example. This deliberate design choice allows for concisely handling multiple cases that share the same or interdependent logic. In an expression context, you can use the [`switch` expression](../operators/switch-expression.md) to evaluate a single expression from a list of candidate expressions based on a pattern match with an expression.
@@ -75,12 +77,12 @@ In an expression context, you can use the [`switch` expression](../operators/swi > Differences between **switch expression** and **switch statement**: > > - **switch statement** is used to control the execution flow within a block of code. -> - **switch expression** is typically used in contexts of value return and value assignment, often as a [expression-bodied members](../../programming-guide/statements-expressions-operators/expression-bodied-members.md). -> - a **switch expression** case section cannot be empty, a **switch statement** can. +> - **switch expression** is typically used in contexts of value return and value assignment, often as [expression-bodied members](../../programming-guide/statements-expressions-operators/expression-bodied-members.md). +> - a **switch expression** case section can't be empty, but a **switch statement** case section can. ### Case guards -A case pattern may not be expressive enough to specify the condition for the execution of the switch section. In such a case, you can use a *case guard*. That is an additional condition that must be satisfied together with a matched pattern. A case guard must be a Boolean expression. You specify a case guard after the `when` keyword that follows a pattern, as the following example shows: +A case pattern might not be expressive enough to specify the condition for the execution of the switch section. In such a case, use a *case guard*. The condition must be satisfied together with a matched pattern. A case guard must be a Boolean expression. Specify a case guard after the `when` keyword that follows a pattern, as the following example shows: :::code language="csharp" source="snippets/selection-statements/SwitchStatement.cs" id="WithCaseGuard"::: diff --git a/docs/csharp/language-reference/statements/using.md b/docs/csharp/language-reference/statements/using.md index 10b93e6601e12..0e705f28f2b88 100644 --- a/docs/csharp/language-reference/statements/using.md +++ b/docs/csharp/language-reference/statements/using.md @@ -1,7 +1,7 @@ --- title: "using statement - ensure the correct use of disposable objects" description: "Use the C# using statement or declaration to ensure the correct use of disposable objects" -ms.date: 03/13/2023 +ms.date: 01/16/2026 f1_keywords: - "using-statement_CSharpKeyword" helpviewer_keywords: @@ -13,13 +13,13 @@ The `using` statement ensures the correct use of an in :::code language="csharp" source="snippets/using/Program.cs" id="Using"::: -When the control leaves the block of the `using` statement, an acquired instance is disposed. In particular, the `using` statement ensures that a disposable instance is disposed even if an exception occurs within the block of the `using` statement. In the preceding example, an opened file is closed after all lines are processed. +When control leaves the block of the `using` statement, the acquired instance is disposed. In particular, the `using` statement ensures that a disposable instance is disposed even if an exception occurs within the block of the `using` statement. In the preceding example, an opened file is closed after all lines are processed. Use the `await using` statement to correctly use an instance: :::code language="csharp" source="snippets/using/Program.cs" id="AwaitUsing"::: -For more information about using of instances, see the [Using async disposable](../../../standard/garbage-collection/implementing-disposeasync.md#using-async-disposable) section of the [Implement a DisposeAsync method](../../../standard/garbage-collection/implementing-disposeasync.md) article. +For more information about using instances, see the [Using async disposable](../../../standard/garbage-collection/implementing-disposeasync.md#using-async-disposable) section of the [Implement a DisposeAsync method](../../../standard/garbage-collection/implementing-disposeasync.md) article. You can also use a `using` *declaration* that doesn't require braces: @@ -27,7 +27,9 @@ You can also use a `using` *declaration* that doesn't require braces: When declared in a `using` declaration, a local variable is disposed at the end of the scope in which it's declared. In the preceding example, disposal happens at the end of a method. -A variable declared by the `using` statement or declaration is readonly. You cannot reassign it or pass it as a [`ref`](../keywords/ref.md) or [`out`](../keywords/method-parameters.md#out-parameter-modifier) parameter. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +A variable declared by the `using` statement or declaration is readonly. You can't reassign it or pass it as a [`ref`](../keywords/ref.md) or [`out`](../keywords/method-parameters.md#out-parameter-modifier) parameter. You can declare several instances of the same type in one `using` statement, as the following example shows: @@ -37,7 +39,7 @@ When you declare several instances in one `using` statement, they are disposed i You can also use the `using` statement and declaration with an instance of a [ref struct](../builtin-types/ref-struct.md) that fits the disposable pattern. That is, it has an instance `Dispose` method that's accessible, parameterless, and has a `void` return type. -A `return` inside a `using` block still guarantees disposal, the compiler rewrites it into a `try/finally`, so the resource’s `Dispose` is always called before the method actually returns. +A `return` inside a `using` block still guarantees disposal. The compiler rewrites it into a `try/finally`, so the resource’s `Dispose` is always called before the method actually returns. The `using` statement can also be of the following form: @@ -48,12 +50,12 @@ using (expression) } ``` -where `expression` produces a disposable instance. The following example demonstrates that: +where `expression` produces a disposable instance. The following example demonstrates that form: :::code language="csharp" source="snippets/using/Program.cs" id="UsingWithExpression"::: > [!WARNING] -> In the preceding example, after control leaves the `using` statement, a disposable instance remains in scope while it's already disposed. If you use that instance further, you might encounter an exception, for example, . That's why we recommend declaring a disposable variable within the `using` statement or with the `using` declaration. +> In the preceding example, after control leaves the `using` statement, a disposable instance remains in scope while it's already disposed. If you use that instance further, you might encounter an exception, for example, . That's why you should declare a disposable variable within the `using` statement or with the `using` declaration. ## C# language specification diff --git a/docs/csharp/language-reference/statements/yield.md b/docs/csharp/language-reference/statements/yield.md index 489c857cd3e1c..4a5a0b1748a2a 100644 --- a/docs/csharp/language-reference/statements/yield.md +++ b/docs/csharp/language-reference/statements/yield.md @@ -1,7 +1,7 @@ --- title: "yield statement - provide the next element in an iterator" description: "Use the yield statement in iterators to provide the next value or signal the end of an iteration" -ms.date: 11/24/2025 +ms.date: 01/16/2026 f1_keywords: - "yield" - "yield_CSharpKeyword" @@ -10,7 +10,7 @@ helpviewer_keywords: --- # yield statement - provide the next element -You use the `yield` statement in an [iterator](../../iterators.md) to provide the next value or signal the end of an iteration. The `yield` statement has the two following forms: +Use the `yield` statement in an [iterator](../../iterators.md) to provide the next value or signal the end of an iteration. The `yield` statement has the two following forms: - `yield return`: to provide the next value in iteration, as the following example shows: @@ -22,7 +22,9 @@ You use the `yield` statement in an [iterator](../../iterators.md) to provide th Iteration also finishes when control reaches the end of an iterator. -In the preceding examples, the return type of iterators is (in nongeneric cases, use as the return type of an iterator). You can also use as the return type of an iterator. That makes an iterator async. Use the [`await foreach` statement](iteration-statements.md#await-foreach) to iterate over iterator's result, as the following example shows: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +In the preceding examples, the return type of iterators is . In nongeneric cases, use as the return type of an iterator. You can also use as the return type of an iterator. That makes an iterator async. Use the [`await foreach` statement](iteration-statements.md#await-foreach) to iterate over iterator's result, as the following example shows: :::code language="csharp" source="snippets/yield/Program.cs" id="IteratorAsync"::: @@ -42,7 +44,7 @@ You can't use the `yield` statements in: ## `using` statements in iterators -You can use [`using` statements](using.md) in iterator methods. Since `using` statements are compiled into `try` blocks with `finally` clauses (and no `catch` blocks), they work correctly with iterators. The disposable resources are properly managed throughout the iterator's execution: +You can use [`using` statements](using.md) in iterator methods. Since `using` statements compile into `try` blocks with `finally` clauses (and no `catch` blocks), they work correctly with iterators. The disposable resources are properly managed throughout the iterator's execution: :::code language="csharp" source="snippets/yield/Program.cs" id="UsingInIterator"::: @@ -50,11 +52,11 @@ As the preceding example shows, the resource acquired in the `using` statement r ## Execution of an iterator -The call of an iterator doesn't execute it immediately, as the following example shows: +Calling an iterator doesn't execute it immediately, as the following example shows: :::code language="csharp" source="snippets/yield/Program.cs" id="IteratorExecution"::: -As the preceding example shows, when you start to iterate over an iterator's result, an iterator is executed until the first `yield return` statement is reached. Then, the execution of an iterator is suspended and the caller gets the first iteration value and processes it. On each subsequent iteration, the execution of an iterator resumes after the `yield return` statement that caused the previous suspension and continues until the next `yield return` statement is reached. The iteration completes when control reaches the end of an iterator or a `yield break` statement. +As the preceding example shows, when you start to iterate over an iterator's result, the iterator executes until the first `yield return` statement is reached. Then, the execution of the iterator is suspended and the caller gets the first iteration value and processes it. On each subsequent iteration, the execution of the iterator resumes after the `yield return` statement that caused the previous suspension and continues until the next `yield return` statement is reached. The iteration completes when control reaches the end of an iterator or a `yield break` statement. ## C# language specification diff --git a/docs/csharp/language-reference/unsafe-code.md b/docs/csharp/language-reference/unsafe-code.md index a7845edd972e8..2150ef51adad3 100644 --- a/docs/csharp/language-reference/unsafe-code.md +++ b/docs/csharp/language-reference/unsafe-code.md @@ -1,7 +1,7 @@ --- title: "Unsafe code, pointers to data, and function pointers" description: Learn about unsafe code, pointers, and function pointers. C# requires you to declare an unsafe context to use these features to directly manipulate memory or function pointers (unmanaged delegates). -ms.date: 02/06/2025 +ms.date: 01/16/2026 f1_keywords: - "functionPointer_CSharpKeyword" helpviewer_keywords: @@ -15,41 +15,43 @@ helpviewer_keywords: --- # Unsafe code, pointer types, and function pointers -Most of the C# code you write is "verifiably safe code." *Verifiably safe code* means .NET tools can verify that the code is safe. In general, safe code doesn't directly access memory using pointers. It also doesn't allocate raw memory. It creates managed objects instead. +Most of the C# code you write is verifiably safe code. *Verifiably safe code* means that .NET tools can verify that the code is safe. In general, safe code doesn't directly access memory by using pointers. It also doesn't allocate raw memory. It creates managed objects instead. -C# supports an [`unsafe`](keywords/unsafe.md) context, in which you can write *unverifiable* code. In an `unsafe` context, code can use pointers, allocate and free blocks of memory, and call methods using function pointers. Unsafe code in C# isn't necessarily dangerous; it's just code whose safety can't be verified. +[!INCLUDE[csharp-version-note](./includes/initial-version.md)] + +C# supports an [`unsafe`](keywords/unsafe.md) context, in which you can write *unverifiable* code. In an `unsafe` context, code can use pointers, allocate and free blocks of memory, and call methods by using function pointers. Unsafe code in C# isn't necessarily dangerous; it's just code whose safety can't be verified. Unsafe code has the following properties: -- Methods, types, and code blocks can be defined as unsafe. +- You can define methods, types, and code blocks as unsafe. - In some cases, unsafe code can increase an application's performance by enabling direct memory access through pointers to avoid array bounds checks. -- Unsafe code is required when you call native functions that require pointers. +- You use unsafe code to call native functions that require pointers. - Using unsafe code introduces security and stability risks. -- The code that contains unsafe blocks must be compiled with the [**AllowUnsafeBlocks**](compiler-options/language.md#allowunsafeblocks) compiler option. +- You must add the [**AllowUnsafeBlocks**](compiler-options/language.md#allowunsafeblocks) compiler option to compile the code that contains unsafe blocks. For information about best practices for unsafe code in C#, see [Unsafe code best practices](../../standard/unsafe-code/best-practices.md). ## Pointer types -In an unsafe context, a type can be a pointer type, in addition to a value type, or a reference type. A pointer type declaration takes one of the following forms: +In an unsafe context, a type can be a pointer type, in addition to a value type or a reference type. A pointer type declaration takes one of the following forms: ``` csharp type* identifier; void* identifier; //allowed but not recommended ``` -The type specified before the `*` in a pointer type is called the **referent type**. +The type you specify before the `*` in a pointer type is the **referent type**. -Pointer types don't inherit from [object](builtin-types/reference-types.md) and no conversions exist between pointer types and `object`. Also, boxing and unboxing don't support pointers. However, you can convert between different pointer types and between pointer types and integral types. +Pointer types don't inherit from [object](builtin-types/reference-types.md), and no conversions exist between pointer types and `object`. Also, boxing and unboxing don't support pointers. However, you can convert between different pointer types and between pointer types and integral types. -When you declare multiple pointers in the same declaration, you write the asterisk (`*`) together with the underlying type only. It isn't used as a prefix to each pointer name. For example: +When you declare multiple pointers in the same declaration, write the asterisk (`*`) together with the underlying type only. It isn't used as a prefix to each pointer name. For example: ```csharp int* p1, p2, p3; // Ok int *p1, *p2, *p3; // Invalid in C# ``` -The garbage collector doesn't keep track of whether an object is being pointed to by any pointer types. If the referrant is an object in the managed heap (including local variables captured by lambda expressions or anonymous delegates), the object must be [pinned](./statements/fixed.md) for as long as the pointer is used. +The garbage collector doesn't keep track of whether an object is being pointed to by any pointer types. If the referent is an object in the managed heap (including local variables captured by lambda expressions or anonymous delegates), you must [pin](./statements/fixed.md) the object for as long as the pointer is used. The value of the pointer variable of type `MyType*` is the address of a variable of type `MyType`. The following are examples of pointer type declarations: @@ -59,7 +61,7 @@ The value of the pointer variable of type `MyType*` is the address of a variable - `char* p`: `p` is a pointer to a char. - `void* p`: `p` is a pointer to an unknown type. -The pointer indirection operator `*` can be used to access the contents at the location pointed to by the pointer variable. For example, consider the following declaration: +You can use the pointer indirection operator `*` to access the contents at the location pointed to by the pointer variable. For example, consider the following declaration: ```csharp int* myVariable; @@ -93,7 +95,7 @@ The following table lists the operators and statements that can operate on point For more information about pointer-related operators, see [Pointer-related operators](operators/pointer-related-operators.md). -Any pointer type can be implicitly converted to a `void*` type. Any pointer type can be assigned the value `null`. Any pointer type can be explicitly converted to any other pointer type using a cast expression. You can also convert any integral type to a pointer type, or any pointer type to an integral type. These conversions require an explicit cast. +Any pointer type can be implicitly converted to a `void*` type. Any pointer type can be assigned the value `null`. You can explicitly convert any pointer type to any other pointer type using a cast expression. You can also convert any integral type to a pointer type, or any pointer type to an integral type. These conversions require an explicit cast. The following example converts an `int*` to a `byte*`. Notice that the pointer points to the lowest addressed byte of the variable. When you successively increment the result, up to the size of `int` (4 bytes), you can display the remaining bytes of the variable. @@ -101,7 +103,7 @@ The following example converts an `int*` to a `byte*`. Notice that the pointer p ## Fixed-size buffers -You can use the `fixed` keyword to create a buffer with a fixed-size array in a data structure. Fixed-size buffers are useful when you write methods that interoperate with data sources from other languages or platforms. The fixed-size buffer can take any attributes or modifiers that are allowed for regular struct members. The only restriction is that the array type must be `bool`, `byte`, `char`, `short`, `int`, `long`, `sbyte`, `ushort`, `uint`, `ulong`, `float`, or `double`. +Use the `fixed` keyword to create a buffer with a fixed-size array in a data structure. Fixed-size buffers are useful when you write methods that interoperate with data sources from other languages or platforms. The fixed-size buffer can take any attributes or modifiers that are allowed for regular struct members. The only restriction is that the array type must be `bool`, `byte`, `char`, `short`, `int`, `long`, `sbyte`, `ushort`, `uint`, `ulong`, `float`, or `double`. ```csharp private fixed char name[30]; @@ -121,7 +123,7 @@ The size of the 128 element `char` array is 256 bytes. Fixed-size [char](builtin The preceding example demonstrates accessing `fixed` fields without pinning. Another common fixed-size array is the [bool](builtin-types/bool.md) array. The elements in a `bool` array are always 1 byte in size. `bool` arrays aren't appropriate for creating bit arrays or buffers. -Fixed-size buffers are compiled with the , which instructs the common language runtime (CLR) that a type contains an unmanaged array that can potentially overflow. Memory allocated using [stackalloc](operators/stackalloc.md) also automatically enables buffer overrun detection features in the CLR. The previous example shows how a fixed-size buffer could exist in an `unsafe struct`. +Fixed-size buffers are compiled with the , which instructs the common language runtime (CLR) that a type contains an unmanaged array that can potentially overflow. Memory allocated by using [stackalloc](operators/stackalloc.md) also automatically enables buffer overrun detection features in the CLR. The preceding example shows how a fixed-size buffer could exist in an `unsafe struct`. ```csharp internal unsafe struct Buffer @@ -150,18 +152,18 @@ internal struct Buffer Fixed-size buffers differ from regular arrays in the following ways: -- Can only be used in an `unsafe` context. -- Can only be instance fields of structs. +- You can only use them in an `unsafe` context. +- They can only be instance fields of structs. - They're always vectors, or one-dimensional arrays. -- The declaration should include the length, such as `fixed char id[8]`. You can't use `fixed char id[]`. +- The declaration must include the length, such as `fixed char id[8]`. You can't use `fixed char id[]`. ## How to use pointers to copy an array of bytes The following example uses pointers to copy bytes from one array to another. -This example uses the [unsafe](keywords/unsafe.md) keyword, which enables you to use pointers in the `Copy` method. The [fixed](statements/fixed.md) statement is used to declare pointers to the source and destination arrays. The `fixed` statement *pins* the location of the source and destination arrays in memory so that garbage collection doesn't move the arrays. The memory blocks for the arrays are unpinned when the `fixed` block is completed. Because the `Copy` method in this example uses the `unsafe` keyword, it must be compiled with the [**AllowUnsafeBlocks**](compiler-options/language.md#allowunsafeblocks) compiler option. +This example uses the [unsafe](keywords/unsafe.md) keyword, which enables you to use pointers in the `Copy` method. The [fixed](statements/fixed.md) statement declares pointers to the source and destination arrays. The `fixed` statement *pins* the location of the source and destination arrays in memory so that garbage collection doesn't move the arrays. The `fixed` block pins the memory blocks for the arrays in the scope of the block. Because the `Copy` method in this example uses the `unsafe` keyword, you must compile it by using the [**AllowUnsafeBlocks**](compiler-options/language.md#allowunsafeblocks) compiler option. -This example accesses the elements of both arrays using indices rather than a second unmanaged pointer. The declaration of the `pSource` and `pTarget` pointers pins the arrays. +This example accesses the elements of both arrays by using indices rather than a second unmanaged pointer. The declaration of the `pSource` and `pTarget` pointers pins the arrays. :::code language="csharp" source="snippets/unsafe-code/FixedKeywordExamples.cs" ID="8"::: @@ -169,23 +171,23 @@ This example accesses the elements of both arrays using indices rather than a se C# provides [`delegate`](builtin-types/reference-types.md#the-delegate-type) types to define safe function pointer objects. Invoking a delegate involves instantiating a type derived from and making a virtual method call to its `Invoke` method. This virtual call uses the `callvirt` IL instruction. In performance critical code paths, using the `calli` IL instruction is more efficient. -You can define a function pointer using the `delegate*` syntax. The compiler calls the function using the `calli` instruction rather than instantiating a `delegate` object and calling `Invoke`. The following code declares two methods that use a `delegate` or a `delegate*` to combine two objects of the same type. The first method uses a delegate type. The second method uses a `delegate*` declaration with the same parameters and return type: +You can define a function pointer by using the `delegate*` syntax. The compiler calls the function by using the `calli` instruction rather than instantiating a `delegate` object and calling `Invoke`. The following code declares two methods that use a `delegate` or a `delegate*` to combine two objects of the same type. The first method uses a delegate type. The second method uses a `delegate*` declaration with the same parameters and return type: :::code language="csharp" source="snippets/unsafe-code/FunctionPointers.cs" ID="UseDelegateOrPointer"::: -The following code shows how you would declare a static local function and invoke the `UnsafeCombine` method using a pointer to that local function: +The following code shows how you declare a static local function and invoke the `UnsafeCombine` method by using a pointer to that local function: :::code language="csharp" source="snippets/unsafe-code/FunctionPointers.cs" ID="InvokeViaFunctionPointer"::: The preceding code illustrates several of the rules on the function accessed as a function pointer: -- Function pointers can only be declared in an `unsafe` context. -- Methods that take a `delegate*` (or return a `delegate*`) can only be called in an `unsafe` context. -- The `&` operator to obtain the address of a function is allowed only on `static` functions. (This rule applies to both member functions and local functions.) +- You can only declare function pointers in an `unsafe` context. +- You can only call methods that take a `delegate*` (or return a `delegate*`) in an `unsafe` context. +- The `&` operator to obtain the address of a function is allowed only on `static` functions. This rule applies to both member functions and local functions. The syntax has parallels with declaring `delegate` types and using pointers. The `*` suffix on `delegate` indicates the declaration is a *function pointer*. The `&` when assigning a method group to a function pointer indicates the operation takes the address of the method. -You can specify the calling convention for a `delegate*` using the keywords `managed` and `unmanaged`. In addition, for `unmanaged` function pointers, you can specify the calling convention. The following declarations show examples of each. The first declaration uses the `managed` calling convention, which is the default. The next four use an `unmanaged` calling convention. Each specifies one of the ECMA 335 calling conventions: `Cdecl`, `Stdcall`, `Fastcall`, or `Thiscall`. The last declaration uses the `unmanaged` calling convention, instructing the CLR to pick the default calling convention for the platform. The CLR chooses the calling convention at run time. +You can specify the calling convention for a `delegate*` by using the keywords `managed` and `unmanaged`. In addition, for `unmanaged` function pointers, you can specify the calling convention. The following declarations show examples of each. The first declaration uses the `managed` calling convention, which is the default. The next four use an `unmanaged` calling convention. Each specifies one of the ECMA 335 calling conventions: `Cdecl`, `Stdcall`, `Fastcall`, or `Thiscall`. The last declaration uses the `unmanaged` calling convention, instructing the CLR to pick the default calling convention for the platform. The CLR chooses the calling convention at run time. :::code language="csharp" source="snippets/unsafe-code/FunctionPointers.cs" ID="UnmanagedFunctionPointers"::: diff --git a/docs/csharp/language-reference/xmldoc/examples.md b/docs/csharp/language-reference/xmldoc/examples.md index 6b7627219dc8b..a95f4fb6f0655 100644 --- a/docs/csharp/language-reference/xmldoc/examples.md +++ b/docs/csharp/language-reference/xmldoc/examples.md @@ -1,12 +1,14 @@ --- title: "Example XML documentation comments" description: See documentation examples on many different C# language elements. Learn which tags to use in different situations and for different language elements. -ms.date: 12/11/2025 +ms.date: 01/16/2026 ms.topic: how-to --- # Example XML documentation comments -This article contains three examples for adding XML documentation comments to most C# language elements. The first example shows how you document a class with different members. The second example shows how you can reuse explanations for a hierarchy of classes or interfaces. The third example shows tags to use for generic classes and members. The second and third examples use concepts that are covered in the first example. +This article contains three examples for adding XML documentation comments to most C# language elements. The first example shows how you document a class with different members. The second example shows how you can reuse explanations for a hierarchy of classes or interfaces. The third example shows tags to use for generic classes and members. The second and third examples use concepts that the first example covers. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] ## Document a class, struct, or interface @@ -24,7 +26,7 @@ The second file, *xml_include_tag.xml*, contains the documentation comments. ## Document a hierarchy of classes and interfaces -The `` element means a type or member *inherits* documentation comments from a base class or interface. You can also use the `` element with the `cref` attribute to inherit comments from a member of the same type. The following example shows ways to use this tag. When you add the `inheritdoc` attribute to a type, member comments are inherited. You can prevent the use of inherited comments by writing comments on the members in the derived type. Those comments are chosen over the inherited comments. +The `` element means a type or member *inherits* documentation comments from a base class or interface. You can also use the `` element with the `cref` attribute to inherit comments from a member of the same type. The following example shows ways to use this tag. When you add the `inheritdoc` attribute to a type, member comments are inherited. You can prevent the use of inherited comments by writing comments on the members in the derived type. The compiler chooses those comments over the inherited comments. :::code language="csharp" source="./snippets/xmldoc/DocComments.cs" ID="InheritDocTag"::: @@ -52,12 +54,12 @@ You might find that the code is obscured by all the comments. The final example :::code language="xml" source="./snippets/xmldoc/include.xml"::: -In the above XML, each member's documentation comments appear directly inside a tag named after what they do. You can choose your own strategy. +In the preceding XML, each member's documentation comments appear directly inside a tag named after what they do. You can choose your own strategy. The code uses the `` tag to reference the appropriate element in the XML file: :::code language="csharp" source="./snippets/xmldoc/include-tag.cs"::: -- The `file` attribute represents the name of the XML file containing the documentation. -- The `path` attribute represents an [XPath](../../../standard/data/xml/xpath-queries-and-namespaces.md) query to the `tag name` present in the specified `file`. -- The `name` attribute represents the name specifier in the tag that precedes the comments. -- The `id` attribute, which you can use in place of `name`, represents the ID for the tag that precedes the comments. +- The `file` attribute is the name of the XML file containing the documentation. +- The `path` attribute is an [XPath](../../../standard/data/xml/xpath-queries-and-namespaces.md) query to the tag name present in the specified file. +- The `name` attribute is the name specifier in the tag that precedes the comments. +- The `id` attribute, which you can use in place of `name`, is the ID for the tag that precedes the comments. diff --git a/docs/csharp/language-reference/xmldoc/index.md b/docs/csharp/language-reference/xmldoc/index.md index fc4d60dc5456a..d139e6187de30 100644 --- a/docs/csharp/language-reference/xmldoc/index.md +++ b/docs/csharp/language-reference/xmldoc/index.md @@ -1,7 +1,7 @@ --- title: "XML API documentation comments comments - document APIs using /// comments" description: Learn about documentation comments. You can create documentation for your code by including XML elements in special comment fields. You can use other tools to build documentation layouts from comments. -ms.date: 02/19/2025 +ms.date: 01/16/2026 f1_keywords: - "cs.xml" helpviewer_keywords: @@ -17,6 +17,8 @@ helpviewer_keywords: C# source files can include structured comments that produce API documentation for the types defined in those files. The C# compiler produces an *XML* file that contains structured data representing the comments and the API signatures. Other tools can process that XML output to create human-readable documentation in the form of web pages or PDF files, for example. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + This process provides many advantages for you to add API documentation in your code: - The C# compiler combines the structure of the C# code with the text of the comments into a single XML document. @@ -42,11 +44,11 @@ You create documentation for your code by writing special comment fields indicat public class MyClass { } ``` -You set either the [**GenerateDocumentationFile**](../../../core/project-sdk/msbuild-props.md#generatedocumentationfile) or [**DocumentationFile**](../../language-reference/compiler-options/output.md#documentationfile) option, and the compiler finds all comment fields with XML tags in the source code and creates an XML documentation file from those comments. When this option is enabled, the compiler generates the [CS1591](../compiler-messages/cs1591.md) warning for any publicly visible member declared in your project without XML documentation comments. +You set either the [**GenerateDocumentationFile**](../../../core/project-sdk/msbuild-props.md#generatedocumentationfile) or [**DocumentationFile**](../../language-reference/compiler-options/output.md#documentationfile) option. The compiler finds all comment fields with XML tags in the source code and creates an XML documentation file from those comments. When you enable this option, the compiler generates the [CS1591](../compiler-messages/cs1591.md) warning for any publicly visible member declared in your project without XML documentation comments. ## XML comment formats -The use of XML doc comments requires delimiters that indicate where a documentation comment begins and ends. You use the following delimiters with the XML documentation tags: +Using XML doc comments requires delimiters that indicate where a documentation comment begins and ends. Use the following delimiters with the XML documentation tags: - `///` Single-line delimiter: The documentation examples and C# project templates use this form. If white space follows the delimiter, it isn't included in the XML output. > [!NOTE] @@ -99,10 +101,10 @@ The use of XML doc comments requires delimiters that indicate where a documentat ``` -To refer to XML elements (for example, your function processes specific XML elements that you want to describe in an XML documentation comment), you can use the standard quoting mechanism (`<` and `>`). To refer to generic identifiers in code reference (`cref`) elements, you can use either the escape characters (for example, `cref="List<T>"`) or braces (`cref="List{T}"`). As a special case, the compiler parses the braces as angle brackets to make the documentation comment less cumbersome to the author when referring to generic identifiers. +To refer to XML elements (for example, your function processes specific XML elements that you want to describe in an XML documentation comment), use the standard quoting mechanism (`<` and `>`). To refer to generic identifiers in code reference (`cref`) elements, use either the escape characters (for example, `cref="List<T>"`) or braces (`cref="List{T}"`). As a special case, the compiler parses the braces as angle brackets to make the documentation comment less cumbersome to the author when referring to generic identifiers. > [!NOTE] -> If you write comments using the single line XML comment delimiter, `///`, but don't include any tags, the compiler adds the text of those comments to the XML output file. However, the output doesn't include XML elements such as ``. Most tools that consume XML comments (including Visual Studio IntelliSense) don't read these comments. +> If you write comments by using the single line XML comment delimiter, `///`, but don't include any tags, the compiler adds the text of those comments to the XML output file. However, the output doesn't include XML elements such as ``. Most tools that consume XML comments (including Visual Studio IntelliSense) don't read these comments. ## Tools that accept XML documentation input @@ -113,37 +115,37 @@ The following tools create output from XML comments: - [Doxygen](https://github.com/doxygen/doxygen): *Doxygen* generates an online documentation browser (in HTML) or an offline reference manual (in LaTeX) from a set of documented source files. There's also support for generating output in RTF (MS Word), PostScript, hyperlinked PDF, compressed HTML, DocBook, and Unix manual pages. You can configure Doxygen to extract the code structure from undocumented source files. > [!NOTE] -> The XML documentation comments aren't metadata; they aren't included in the compiled assembly and therefore they aren't accessible through reflection. +> The XML documentation comments aren't metadata. The compiler doesn't include them in the compiled assembly, so they're not accessible through reflection. ### ID strings -Each type or member is stored in an element in the output XML file. Each of those elements has a unique ID string that identifies the type or member. The ID string must account for operators, parameters, return values, generic type parameters, `ref`, `in`, and `out` parameters. To encode all those potential elements, the compiler follows clearly defined rules for generating the ID strings. Programs that process the XML file use the ID string to identify the corresponding .NET metadata or reflection item that the documentation applies to. +The compiler writes each type or member to an element in the output XML file. Each element has a unique ID string that identifies the type or member. The ID string includes information about operators, parameters, return values, generic type parameters, `ref`, `in`, and `out` parameters. To encode all those potential elements, the compiler follows clearly defined rules for generating the ID strings. Programs that process the XML file use the ID string to identify the corresponding .NET metadata or reflection item that the documentation applies to. -The compiler observes the following rules when it generates the ID strings: +The compiler follows these rules when it generates the ID strings: -- No white space is in the string. -- The first part of the string identifies the kind of member using a single character followed by a colon. The following member types are used: +- The string contains no white space. +- The string starts with a single character and a colon that identifies the kind of member. Use the following member types: - | Character | Member type | Notes | - |--|--|--| - | `N` | namespace | You can't add documentation comments to a namespace, but you can make `cref` references to them, where supported. | - | `T` | type | A type is a class, interface, struct, enum, or delegate. | - | `F` | field | | - | `P` | property | Includes indexers or other indexed properties. | - | `M` | method | Includes special methods, such as constructors and operators. | - | `E` | event | | - | `!` | error string | The rest of the string provides information about the error. The C# compiler generates error information for links that can't be resolved. | + | Character | Member type | Notes | + |-----------|--------------|--| + | `N` | namespace | You can't add documentation comments to a namespace, but you can make `cref` references to them, where supported. | + | `T` | type | A type is a class, interface, struct, enum, or delegate. | + | `F` | field | | + | `P` | property | Includes indexers or other indexed properties. | + | `M` | method | Includes special methods, such as constructors and operators. | + | `E` | event | | + | `!` | error string | The rest of the string provides information about the error. The C# compiler generates error information for links that can't be resolved. | -- The second part of the string is the fully qualified name of the item, starting at the root of the namespace. The name of the item, its enclosing type(s), and namespace are separated by periods. If the name of the item itself has periods, they're replaced with the hash-sign ('#'). The grammar assumes that no item has a hash-sign directly in its name. For example, the fully qualified name of the String constructor is "System.String.#ctor". +- The second part of the string is the fully qualified name of the item, starting at the root of the namespace. The name of the item, its enclosing types, and namespace are separated by periods. If the name of the item itself has periods, the compiler replaces them with the hash-sign ('#'). The grammar assumes that no item has a hash-sign directly in its name. For example, the fully qualified name of the String constructor is "System.String.#ctor". - For properties and methods, the parameter list enclosed in parentheses follows. If there are no parameters, no parentheses are present. The parameters are separated by commas. The encoding of each parameter follows directly how it's encoded in a .NET signature (See for definitions of the all caps elements in the following list): - Base types. Regular types (`ELEMENT_TYPE_CLASS` or `ELEMENT_TYPE_VALUETYPE`) are represented as the fully qualified name of the type. - - Intrinsic types (for example, `ELEMENT_TYPE_I4`, `ELEMENT_TYPE_OBJECT`, `ELEMENT_TYPE_STRING`, `ELEMENT_TYPE_TYPEDBYREF`, and `ELEMENT_TYPE_VOID`) are represented as the fully qualified name of the corresponding full type. For example, `System.Int32` or `System.TypedReference`. + - Intrinsic types, such as `ELEMENT_TYPE_I4`, `ELEMENT_TYPE_OBJECT`, `ELEMENT_TYPE_STRING`, `ELEMENT_TYPE_TYPEDBYREF`, and `ELEMENT_TYPE_VOID`, are represented as the fully qualified name of the corresponding full type. For example, `System.Int32` or `System.TypedReference`. - `ELEMENT_TYPE_PTR` is represented as a '\*' following the modified type. - `ELEMENT_TYPE_BYREF` is represented as a '\@' following the modified type. - `ELEMENT_TYPE_CMOD_OPT` is represented as a '!' and the fully qualified name of the modifier class, following the modified type. - `ELEMENT_TYPE_SZARRAY` is represented as "[]" following the element type of the array. - `ELEMENT_TYPE_ARRAY` is represented as [*lower bound*:`size`,*lower bound*:`size`] where the number of commas is the rank - 1, and the lower bounds and size of each dimension, if known, are represented in decimal. The lower bound and size are omitted if they aren't specified. If the lower bound and size for a particular dimension is omitted, the ':' is omitted as well. For example, a two-dimensional array with 1 as the lower bounds and unspecified sizes is [1:,1:]. -- For conversion operators only (`op_Implicit` and `op_Explicit`), the return value of the method is encoded as a `~` followed by the return type. For example: +- For conversion operators only (`op_Implicit` and `op_Explicit`), the method return value is encoded as a `~` followed by the return type. For example: `` is the tag for the cast operator `public static explicit operator int (decimal value);` declared in the `System.Decimal` class. - For generic types, the name of the type is followed by a backtick and then a number that indicates the number of generic type parameters. For example: ```` is the tag for a type that is defined as `public class SampleClass`. @@ -157,7 +159,7 @@ The compiler observes the following rules when it generates the ID strings: - return type - `ELEMENT_TYPE_SENTINEL` -The following examples show how the ID strings for a class and its members are generated: +The following examples show how the compiler generates the ID strings for a class and its members: :::code language="csharp" source="./snippets/xmldoc/idstrings.cs"::: diff --git a/docs/csharp/language-reference/xmldoc/recommended-tags.md b/docs/csharp/language-reference/xmldoc/recommended-tags.md index 69f9d5844e746..34f5a3fc64a49 100644 --- a/docs/csharp/language-reference/xmldoc/recommended-tags.md +++ b/docs/csharp/language-reference/xmldoc/recommended-tags.md @@ -1,7 +1,7 @@ --- title: "Recommended XML documentation tags" description: This article provides the syntax and definitions for recommended tags on types, and their members for XML documentation. -ms.date: 08/15/2024 +ms.date: 01/16/2026 f1_keywords: - "" - "summary" @@ -95,23 +95,25 @@ helpviewer_keywords: C# documentation comments use XML elements to define the structure of the output documentation. One consequence of this feature is that you can add any valid XML in your documentation comments. The C# compiler copies these elements into the output XML file. While you can use any valid XML in your comments (including any valid HTML element), documenting code is recommended for many reasons. -What follows are some recommendations, general use case scenarios, and things that you should know when using XML documentation tags in your C# code. While you can put any tags into your documentation comments, this article describes the recommended tags for the most common language constructs. In all cases, you should adhere to these recommendations: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -- For the sake of consistency, all publicly visible types and their public members should be documented. -- Private members can also be documented using XML comments. However, it exposes the inner (potentially confidential) workings of your library. +What follows are some recommendations, general use case scenarios, and things that you should know when using XML documentation tags in your C# code. While you can put any tags into your documentation comments, this article describes the recommended tags for the most common language constructs. Adhere to these recommendations: + +- For the sake of consistency, document all publicly visible types and their public members. +- You can also document private members by using XML comments. However, this approach exposes the inner (potentially confidential) workings of your library. - At a bare minimum, types and their members should have a `` tag. -- Documentation text should be written using complete sentences ending with full stops. +- Write documentation text using complete sentences that end with full stops. - Partial classes are fully supported, and documentation information is concatenated into a single entry for each type. If both declarations of a partial member have documentation comments, the comments on the implementing declaration are written to the output XML. XML documentation starts with `///`. When you create a new project, the templates put some starter `///` lines in for you. The processing of these comments has some restrictions: - The documentation must be well-formed XML. If the XML isn't well formed, the compiler generates a warning. The documentation file contains a comment that says that an error was encountered. - Some of the recommended tags have special meanings: - - The `` tag is used to describe parameters. If used, the compiler verifies that the parameter exists and that all parameters are described in the documentation. If the verification fails, the compiler issues a warning. - - The `cref` attribute can be attached to any tag to reference a code element. The compiler verifies that this code element exists. If the verification fails, the compiler issues a warning. The compiler respects any `using` directives when it looks for a type described in the `cref` attribute. - - The `` tag is used by IntelliSense inside Visual Studio to display additional information about a type or member. + - The `` tag describes parameters. If you use this tag, the compiler verifies that the parameter exists and that all parameters are described in the documentation. If the verification fails, the compiler issues a warning. + - Attach the `cref` attribute to any tag to reference a code element. The compiler verifies that this code element exists. If the verification fails, the compiler issues a warning. The compiler respects any `using` directives when it looks for a type described in the `cref` attribute. + - IntelliSense inside Visual Studio uses the `` tag to display additional information about a type or member. > [!NOTE] - > The XML file does not provide full information about the type and members (for example, it does not contain any type information). To get full information about a type or member, use the documentation file together with reflection on the actual type or member. + > The XML file doesn't provide full information about the type and members (for example, it doesn't contain any type information). To get full information about a type or member, use the documentation file together with reflection on the actual type or member. - Developers are free to create their own set of tags. The compiler copies these tags to the output file. Some of the recommended tags can be used on any language element. Others have more specialized usage. Finally, some of the tags are used to format text in your documentation. This article describes the recommended tags organized by their use. @@ -149,14 +151,14 @@ The compiler verifies the syntax of the elements followed by a single \* in the - [``](#seealso) \* - [`cref`](#cref-attribute) - [`href`](#href-attribute) -- [Tags for generic types and methods](#generic-types-and-methods) - These tags are used only on generic types and methods - - [``](#typeparam) \*: The value of this element is displayed in IntelliSense in Visual Studio. +- [Tags for generic types and methods](#generic-types-and-methods) - Use these tags only on generic types and methods. + - [``](#typeparam) \*: IntelliSense in Visual Studio shows the value of this element. - [``](#typeparamref) > [!NOTE] -> Documentation comments cannot be applied to a namespace. +> You can't apply documentation comments to a namespace. -If you want angle brackets to appear in the text of a documentation comment, use the HTML encoding of `<` and `>`, which is `<` and `>` respectively. This encoding is shown in the following example. +If you want angle brackets to appear in the text of a documentation comment, use the HTML encoding of `<` and `>`, which is `<` and `>` respectively. The following example shows this encoding. ```csharp /// @@ -172,7 +174,7 @@ If you want angle brackets to appear in the text of a documentation comment, use description ``` -The `` tag should be used to describe a type or a type member. Use [``](#remarks) to add supplemental information to a type description. Use the [cref attribute](#cref-attribute) to enable documentation tools such as [DocFX](https://dotnet.github.io/docfx/) and [Sandcastle](https://github.com/EWSoftware/SHFB) to create internal hyperlinks to documentation pages for code elements. The text for the `` tag is displayed in IntelliSense and in the Object Browser window. +Use the `` tag to describe a type or a type member. Use [``](#remarks) to add supplemental information to a type description. Use the [cref attribute](#cref-attribute) to enable documentation tools such as [DocFX](https://dotnet.github.io/docfx/) and [Sandcastle](https://github.com/EWSoftware/SHFB) to create internal hyperlinks to documentation pages for code elements. The text for the `` tag appears in IntelliSense and in the Object Browser window. ### `` @@ -182,7 +184,7 @@ description ``` -The `` tag is used to add information about a type or a type member, supplementing the information specified with [``](#summary). This information is displayed in the Object Browser window. This tag can include more lengthy explanations. You might find that using `CDATA` sections for markdown make writing it more convenient. Tools such as [docfx](https://dotnet.github.io/docfx/) process the markdown text in `CDATA` sections. +Use the `` tag to add information about a type or a type member, supplementing the information specified with [``](#summary). This information appears in the Object Browser window. This tag can include more lengthy explanations. You might find that using `CDATA` sections for markdown make writing it more convenient. Tools such as [docfx](https://dotnet.github.io/docfx/) process the markdown text in `CDATA` sections. ## Document members @@ -192,7 +194,7 @@ The `` tag is used to add information about a type or a type member, su description ``` -The `` tag should be used in the comment for a method declaration to describe the return value. +Use the `` tag in the comment for a method declaration to describe the return value. ### `` @@ -202,7 +204,7 @@ The `` tag should be used in the comment for a method declaration to de - `name`: The name of a method parameter. Enclose the name in quotation marks ("). The names for parameters must match the API signature. If one or more parameters aren't covered, the compiler issues a warning. The compiler also issues a warning if the value of `name` doesn't match a formal parameter in the method declaration. -The `` tag should be used in the comment for a method declaration to describe one of the parameters for the method. To document multiple parameters, use multiple `` tags. The text for the `` tag is displayed in IntelliSense, the Object Browser, and the Code Comment Web Report. +Use the `` tag in the comment for a method declaration to describe one of the parameters for the method. To document multiple parameters, use multiple `` tags. The text for the `` tag appears in IntelliSense, the Object Browser, and the Code Comment Web Report. ### `` @@ -212,7 +214,7 @@ The `` tag should be used in the comment for a method declaration to desc - `name`: The name of the parameter to refer to. Enclose the name in quotation marks ("). -The `` tag gives you a way to indicate that a word in the code comments, for example in a `` or `` block refers to a parameter. The XML file can be processed to format this word in some distinct way, such as with a bold or italic font. +The `` tag provides a way to indicate that a word in the code comments, such as in a `` or `` block, refers to a parameter. You can process the XML file to format this word in a distinct way, such as by using a bold or italic font. ### `` @@ -220,9 +222,9 @@ The `` tag gives you a way to indicate that a word in the code comment description ``` -- cref = "`member`": A reference to an exception that is available from the current compilation environment. The compiler checks that the given exception exists and translates `member` to the canonical element name in the output XML. `member` must appear within quotation marks ("). +- cref = "`member`": A reference to an exception that's available from the current compilation environment. The compiler checks that the given exception exists and translates `member` to the canonical element name in the output XML. `member` must appear within quotation marks ("). -The `` tag lets you specify which exceptions can be thrown. This tag can be applied to definitions for methods, properties, events, and indexers. +The `` tag lets you specify which exceptions can be thrown. Apply this tag to definitions for methods, properties, events, and indexers. ### `` @@ -230,7 +232,7 @@ The `` tag lets you specify which exceptions can be thrown. This tag property-description ``` -The `` tag lets you describe the value that a property represents. When you add a property via code wizard in the Visual Studio .NET development environment, it adds a [``](#summary) tag for the new property. You manually add a `` tag to describe the value that the property represents. +The `` tag lets you describe the value that a property represents. When you add a property by using the code wizard in the Visual Studio .NET development environment, it adds a [``](#summary) tag for the new property. You manually add a `` tag to describe the value that the property represents. ## Format documentation output @@ -247,7 +249,7 @@ The `` tag lets you describe the value that a property represents. When y ``` -The `` tag is for use inside a tag, such as [``](#summary), [``](#remarks), or [``](#returns), and lets you add structure to the text. The `` tag creates a double spaced paragraph. Use the `
` tag if you want a single spaced paragraph. +Use the `` tag inside a tag, such as [``](#summary), [``](#remarks), or [``](#returns), to add structure to the text. The `` tag creates a double spaced paragraph. Use the `
` tag if you want a single spaced paragraph. Here's an example showing the difference between `` and `
`: @@ -276,17 +278,17 @@ Here's an example showing the difference between `` and `
`: ``` -The `` block is used to define the heading row of either a table or definition list. +Use the `` block to define the heading row of either a table or definition list. When defining a table: -* You only need to supply an entry for `term` in the heading. -* Each item in the list is specified with an `` block. For each `item`, you only need to supply an entry for `description`. +* Supply an entry for `term` in the heading. +* Specify each item in the list with an `` block. For each `item`, supply an entry for `description`. When creating a definition list: -* You must supply an entry for `term` in the heading. -* Each item in the list is specified with an `` block. Each `item` must contain both a `term` and `description`. +* Supply an entry for `term` in the heading. +* Specify each item in the list with an `` block. Each `item` must contain both a `term` and `description`. A list or table can have as many `` blocks as needed. @@ -296,7 +298,7 @@ A list or table can have as many `` blocks as needed. text ``` -The `` tag gives you a way to indicate that text within a description should be marked as code. Use [``](#code) to indicate multiple lines as code. +Use the `` tag to mark text within a description as code. Use [``](#code) to indicate multiple lines as code. ### `` @@ -307,7 +309,7 @@ The `` tag gives you a way to indicate that text within a description should ``` -The `` tag is used to indicate multiple lines of code. Use [``](#c) to indicate that single-line text within a description should be marked as code. +Use the `` tag to indicate multiple lines of code. Use [``](#c) to mark single-line text within a description as code. ### `` @@ -321,7 +323,7 @@ This shows how to increment an integer. ``` -The `` tag lets you specify an example of how to use a method or other library member. An example commonly involves using the [``](#code) tag. +Use the `` tag to provide an example of how to use a method or other library member. An example commonly involves using the [``](#code) tag. ### `` @@ -329,7 +331,7 @@ The `` tag lets you specify an example of how to use a method or other text ``` -The `` tag is used to make text bold within documentation comments. This HTML formatting tag is validated by the compiler and Visual Studio, and the formatted text appears in IntelliSense and generated documentation. +Use the `` tag to make text bold within documentation comments. The compiler and Visual Studio validate this HTML formatting tag. The formatted text appears in IntelliSense and generated documentation. ### `` @@ -337,7 +339,7 @@ The `` tag is used to make text bold within documentation comments. This HTML text ``` -The `` tag is used to make text italic within documentation comments. This HTML formatting tag is validated by the compiler and Visual Studio, and the formatted text appears in IntelliSense and generated documentation. +Use the `` tag to make text italic within documentation comments. The compiler and Visual Studio validate this HTML formatting tag. The formatted text appears in IntelliSense and generated documentation. ### `` @@ -345,7 +347,7 @@ The `` tag is used to make text italic within documentation comments. This HT text ``` -The `` tag is used to underline text within documentation comments. This HTML formatting tag is validated by the compiler and Visual Studio, and the formatted text appears in IntelliSense and generated documentation. +Use the `` tag to underline text within documentation comments. The compiler and Visual Studio validate this HTML formatting tag. The formatted text appears in IntelliSense and generated documentation. ### `
` @@ -353,7 +355,7 @@ The `` tag is used to underline text within documentation comments. This HTML Line one
Line two ``` -The `
` tag is used to insert a line break within documentation comments. Use this tag when you want a single spaced paragraph, as opposed to the `` tag which creates double spaced paragraphs. +Use the `
` tag to insert a line break within documentation comments. Use this tag when you want a single spaced paragraph, as opposed to the `` tag which creates double spaced paragraphs. ### `` @@ -361,7 +363,7 @@ The `
` tag is used to insert a line break within documentation comments. Us
Link text ``` -The `` tag is used to create hyperlinks within documentation comments. The `href` attribute specifies the URL to link to. This HTML formatting tag is validated by the compiler and Visual Studio. +Use the `` tag to create hyperlinks within documentation comments. The `href` attribute specifies the URL to link to. The compiler and Visual Studio validate this HTML formatting tag. > [!NOTE] > The compiler also validates the `` tag, which is deprecated HTML. Use the [``](#c) tag instead for inline code formatting. @@ -374,17 +376,17 @@ The `` tag is used to create hyperlinks within documentation comments. The `h ``` -Inherit XML comments from base classes, interfaces, and similar methods. Using `inheritdoc` eliminates unwanted copying and pasting of duplicate XML comments and automatically keeps XML comments synchronized. When you add the `` tag to a type, all members inherit the comments as well. +Inherit XML comments from base classes, interfaces, and similar methods. By using `inheritdoc`, you eliminate unwanted copying and pasting of duplicate XML comments and automatically keep XML comments synchronized. When you add the `` tag to a type, all members inherit the comments as well. -- `cref`: Specify the member to inherit documentation from. Already defined tags on the current member aren't overridden by the inherited ones. -- `path`: The XPath expression query that results in a node set to show. You can use this attribute to filter the tags to include or exclude from the inherited documentation. +- `cref`: Specify the member to inherit documentation from. The inherited tags don't override already defined tags on the current member. +- `path`: The XPath expression query that results in a node set to show. Use this attribute to filter the tags to include or exclude from the inherited documentation. > [!NOTE] -> Visual Studio provides automatic inheritance of XML documentation for undocumented members that override or implement documented members. This feature displays inherited documentation in IntelliSense and Quick Info without requiring the `` tag. However, this automatic inheritance only applies within the Visual Studio IDE and doesn't affect the XML documentation file generated by the compiler. +> Visual Studio automatically inherits XML documentation for undocumented members that override or implement documented members. This feature displays inherited documentation in IntelliSense and Quick Info without requiring the `` tag. However, this automatic inheritance only applies within the Visual Studio IDE and doesn't affect the XML documentation file generated by the compiler. > -> For public APIs in libraries that you distribute, you should explicitly use the `` tag or provide complete documentation to ensure the generated XML documentation file includes all necessary information for consumers of your library. +> For public APIs in libraries that you distribute, explicitly use the `` tag or provide complete documentation to ensure the generated XML documentation file includes all necessary information for consumers of your library. -Add your XML comments in base classes or interfaces and let inheritdoc copy the comments to implementing classes. Add your XML comments to your synchronous methods and let inheritdoc copy the comments to your asynchronous versions of the same methods. If you want to copy the comments from a specific member, you use the `cref` attribute to specify the member. +Add your XML comments in base classes or interfaces and let inheritdoc copy the comments to implementing classes. Add your XML comments to your synchronous methods and let inheritdoc copy the comments to your asynchronous versions of the same methods. To copy the comments from a specific member, use the `cref` attribute to specify the member. ### `` @@ -392,12 +394,12 @@ Add your XML comments in base classes or interfaces and let inheritdoc copy the ``` -- `filename`: The name of the XML file containing the documentation. The file name can be qualified with a path relative to the source code file. Enclose `filename` in single quotation marks (' '). +- `filename`: The name of the XML file containing the documentation. You can qualify the file name with a path relative to the source code file. Enclose `filename` in single quotation marks (' '). - `tagpath`: The path of the tags in `filename` that leads to the tag `name`. Enclose the path in single quotation marks (' '). -- `name`: The name specifier in the tag that precedes the comments; `name` has an `id`. +- `name`: The name specifier in the tag that precedes the comments. The `name` specifier has an `id`. - `id`: The ID for the tag that precedes the comments. Enclose the ID in quotation marks ("). -The `` tag lets you refer to comments in another file that describe the types and members in your source code. Including an external file is an alternative to placing documentation comments directly in your source code file. By putting the documentation in a separate file, you can apply source control to the documentation separately from the source code. One person can have the source code file checked out and someone else can have the documentation file checked out. The `` tag uses the XML XPath syntax. Refer to XPath documentation for ways to customize your `` use. +By using the `` tag, you can refer to comments in another file that describe the types and members in your source code. Including an external file is an alternative to placing documentation comments directly in your source code file. By putting the documentation in a separate file, you can apply source control to the documentation separately from the source code. One person can have the source code file checked out and someone else can have the documentation file checked out. The `` tag uses the XML XPath syntax. Refer to XPath documentation for ways to customize your `` use. For example, the following source code uses the `` tag to include remarks. The file path is relative to the source. @@ -435,11 +437,11 @@ The XML output for this method is shown in the following example: ``` -- `cref="member"`: A reference to a member or field that is available to be called from the current compilation environment. The compiler checks that the given code element exists and passes `member` to the element name in the output XML. Place *member* within quotation marks ("). You can provide different link text for a "cref", by using a separate closing tag. -- `href="link"`: A clickable link to a given URL. For example, `GitHub` produces a clickable link with text :::no-loc text="GitHub"::: that links to `https://github.com`. Use `href` instead of `cref` when linking to external web pages, as `cref` is designed for code references and won't create clickable links for external URLs. +- `cref="member"`: A reference to a member or field that you can call from the current compilation environment. The compiler checks that the given code element exists and passes `member` to the element name in the output XML. Place *member* within quotation marks ("). You can provide different link text for a `cref`, by using a separate closing tag. +- `href="link"`: A clickable link to a given URL. For example, `GitHub` produces a clickable link with text :::no-loc text="GitHub"::: that links to `https://github.com`. Use `href` instead of `cref` when linking to external web pages, as `cref` is designed for code references and doesn't create clickable links for external URLs. - `langword="keyword"`: A language keyword, such as `true` or one of the other valid [keywords](../keywords/index.md). -The `` tag lets you specify a link from within text. Use [``](#seealso) to indicate that text should be placed in a See Also section. Use the [cref attribute](#cref-attribute) to create internal hyperlinks to documentation pages for code elements. You include the type parameters to specify a reference to a generic type or method, such as `cref="IDictionary{T, U}"`. Also, ``href`` is a valid attribute that functions as a hyperlink. +The `` tag lets you specify a link from within text. Use [``](#seealso) to indicate that text should be placed in a See Also section. Use the [cref attribute](#cref-attribute) to create internal hyperlinks to documentation pages for code elements. Include the type parameters to specify a reference to a generic type or method, such as `cref="IDictionary{T, U}"`. Also, ``href`` is a valid attribute that functions as a hyperlink. Here's an example showing the difference between `cref` and `href` when referencing external URLs: @@ -453,7 +455,7 @@ Here's an example showing the difference between `cref` and `href` when referenc Link Text ``` -- `cref="member"`: A reference to a member or field that is available to be called from the current compilation environment. The compiler checks that the given code element exists and passes `member` to the element name in the output XML. `member` must appear within quotation marks ("). +- `cref="member"`: A reference to a member or field that you can call from the current compilation environment. The compiler checks that the given code element exists and passes `member` to the element name in the output XML. `member` must appear within quotation marks ("). - `href="link"`: A clickable link to a given URL. For example, `GitHub` produces a clickable link with text :::no-loc text="GitHub"::: that links to `https://github.com`. The `` tag lets you specify the text that you might want to appear in a **See Also** section. Use [``](#see) to specify a link from within text. You can't nest the `seealso` tag inside the `summary` tag.