diff --git a/docs/csharp/language-reference/keywords/abstract.md b/docs/csharp/language-reference/keywords/abstract.md index 3dee5bb11c851..077c875b7a80a 100644 --- a/docs/csharp/language-reference/keywords/abstract.md +++ b/docs/csharp/language-reference/keywords/abstract.md @@ -1,21 +1,25 @@ --- description: "abstract - C# Reference" title: "abstract keyword" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "abstract" - "abstract_CSharpKeyword" helpviewer_keywords: - "abstract keyword [C#]" -ms.assetid: b0797770-c1f3-4b4d-9441-b9122602a6bb --- # abstract (C# Reference) -The `abstract` modifier indicates that the thing being modified has a missing or incomplete implementation. The abstract modifier can be used with classes, methods, properties, indexers, and events. Use the `abstract` modifier in a class declaration to indicate that a class is intended only to be a base class of other classes, not instantiated on its own. Members marked as abstract must be implemented by non-abstract classes that derive from the abstract class. +The `abstract` modifier indicates that its target has a missing or incomplete implementation. Use the abstract modifier with classes, methods, properties, indexers, and events. Use the `abstract` modifier in a class declaration to indicate that a class is intended only to be a base class of other classes, not instantiated on its own. Non-abstract classes that derive from the abstract class must implement members marked as abstract. -Abstract classes can contain both abstract members (which have no implementation and must be overridden in derived classes) and fully implemented members (such as regular methods, properties, and constructors). This allows abstract classes to provide common functionality while still requiring derived classes to implement specific abstract members. - -## Example 1 - Abstract class with mixed members +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +Abstract classes can contain both abstract members (which have no implementation and must be overridden in derived classes) and fully implemented members (such as regular methods, properties, and constructors). This feature allows abstract classes to provide common functionality while still requiring derived classes to implement specific abstract members. + +> [!NOTE] +> Interface members are `abstract` by default. + +## Abstract class with mixed members The following example demonstrates an abstract class that contains both implemented methods and abstract members: @@ -23,93 +27,77 @@ The following example demonstrates an abstract class that contains both implemen In this example, the `Vehicle` abstract class provides: -- **Implemented members**: `GetInfo()` method, `StartEngine()` method, and constructor - these provide common functionality for all vehicles. -- **Abstract members**: `Move()` method and `MaxSpeed` property - these must be implemented by each specific vehicle type. +- **Implemented members**: `GetInfo()` method, `StartEngine()` method, and constructor - these members provide common functionality for all vehicles. +- **Abstract members**: `Move()` method and `MaxSpeed` property - these members must be implemented by each specific vehicle type. This design allows the abstract class to provide shared functionality while ensuring that derived classes implement vehicle-specific behavior. -## Example 2 - - In this example, the class `Square` must provide an implementation of `GetArea` because it derives from `Shape`: - - [!code-csharp[csrefKeywordsModifiers#1](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#1)] - - Abstract classes have the following features: - -- An abstract class cannot be instantiated. - -- An abstract class may contain abstract methods and accessors. - +## Concrete class derived from an abstract class + +In this example, the class `Square` must provide an implementation of `GetArea` because it derives from `Shape`: + +:::code language="csharp" source="snippets/csrefKeywordsModifiers.cs" id="1"::: + +Abstract classes have the following features: + +- You can't create an instance of an abstract class. +- An abstract class can contain abstract methods and accessors. - An abstract class can also contain implemented methods, properties, fields, and other members that provide functionality to derived classes. - -- It is not possible to modify an abstract class with the [sealed](./sealed.md) modifier because the two modifiers have opposite meanings. The `sealed` modifier prevents a class from being inherited and the `abstract` modifier requires a class to be inherited. - -- A non-abstract class derived from an abstract class must include actual implementations of all inherited abstract methods and accessors. - - Use the `abstract` modifier in a method or property declaration to indicate that the method or property does not contain implementation. - - Abstract methods have the following features: - -- An abstract method is implicitly a virtual method. - -- Abstract method declarations are only permitted in abstract classes. - -- Because an abstract method declaration provides no actual implementation, there is no method body; the method declaration simply ends with a semicolon and there are no curly braces ({ }) following the signature. For example: - - ```csharp - public abstract void MyMethod(); - ``` - - The implementation is provided by a method [override](./override.md), which is a member of a non-abstract class. - -- It is an error to use the [static](./static.md) or [virtual](./virtual.md) modifiers in an abstract method declaration. - - Abstract properties behave like abstract methods, except for the differences in declaration and invocation syntax. - -- It is an error to use the `abstract` modifier on a static property. - -- An abstract inherited property can be overridden in a derived class by including a property declaration that uses the [override](./override.md) modifier. - - For more information about abstract classes, see [Abstract and Sealed Classes and Class Members](../../programming-guide/classes-and-structs/abstract-and-sealed-classes-and-class-members.md). - - An abstract class must provide implementation for all interface members. - - An abstract class that implements an interface might map the interface methods onto abstract methods. For example: - -[!code-csharp[csrefKeywordsModifiers#2](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#2)] - -## Example 3 - - In this example, the class `DerivedClass` is derived from an abstract class `BaseClass`. The abstract class contains an abstract method, `AbstractMethod`, and two abstract properties, `X` and `Y`. - -[!code-csharp[csrefKeywordsModifiers#3](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#3)] - - In the preceding example, if you attempt to instantiate the abstract class by using a statement like this: - -```csharp -BaseClass bc = new BaseClass(); // Error -``` - -You will get an error saying that the compiler cannot create an instance of the abstract class 'BaseClass'. +- You can't use the [`sealed`](./sealed.md) modifier on an abstract class because the two modifiers have opposite meanings. The `sealed` modifier prevents a class from being inherited and the `abstract` modifier requires a class to be inherited. +- A non-abstract class derived from an abstract class must include actual implementations of all inherited abstract methods and accessors. + +Use the `abstract` modifier in a method or property declaration to indicate that the method or property doesn't contain implementation. + +Abstract methods have the following features: + +- An abstract method is implicitly a virtual method. +- Abstract method declarations are only permitted in abstract classes. +- Because an abstract method declaration provides no actual implementation, there's no method body. The method declaration simply ends with a semicolon. For example: + + ```csharp + public abstract void MyMethod(); + ``` -Nonetheless, it is possible to use an abstract class constructor, as in the example below + The implementation is provided by a method [`override`](./override.md), which is a member of a non-abstract class. -## Example 4 +- It's an error to use the [`static`](./static.md) or [`virtual`](./virtual.md) modifiers in an abstract method declaration in a `class` type. You can declare `static abstract` and `static virtual` methods in interfaces. -[!code-csharp[csrefKeywordsModifiers#27](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#27)] + Abstract properties behave like abstract methods, except for the differences in declaration and invocation syntax. -The `Shape` class is declared `abstract`, which means it cannot be instantiated directly. Instead, it serves as a blueprint for other classes. +- It's an error to use the `abstract` modifier on a static property in a `class` type. You can declare `static abstract` or `static virtual` properties in interface declarations. +- An abstract inherited property can be overridden in a derived class by including a property declaration that uses the [`override`](./override.md) modifier. -- Even though you can't create objects of an abstract class, it can still have a constructor. This constructor is typically `protected`, meaning it can only be accessed from derived classes. +For more information about abstract classes, see [Abstract and Sealed Classes and Class Members](../../programming-guide/classes-and-structs/abstract-and-sealed-classes-and-class-members.md). + +An abstract class must provide implementation for all interface members. An abstract class that implements an interface might map the interface methods onto abstract methods. For example: + +:::code language="csharp" source="snippets/csrefKeywordsModifiers.cs" id="2"::: + +In the following example, the class `DerivedClass` derives from an abstract class `BaseClass`. The abstract class contains an abstract method, `AbstractMethod`, and two abstract properties, `X` and `Y`. + +:::code language="csharp" source="snippets/csrefKeywordsModifiers.cs" id="3"::: + +In the preceding example, if you attempt to instantiate the abstract class by using a statement like this: + +```csharp +BaseClass bc = new BaseClass(); // Error +``` + +You get an error saying that the compiler can't create an instance of the abstract class 'BaseClass'. Nonetheless, you can use an abstract class constructor, as shown in the following example. + +:::code language="csharp" source="snippets/csrefKeywordsModifiers.cs" id="27"::: + +The `Shape` class is declared `abstract`, which means you can't instantiate it directly. Instead, it serves as a blueprint for other classes. + +- Even though you can't create objects of an abstract class, it can still have a constructor. This constructor is typically `protected`, meaning only derived classes can access it. In this case, the `Shape` constructor takes a `color` parameter and initializes the `Color` property. It also prints a message to the console. The `public Square(string color, double side) : base(color)` part calls the base class's constructor (`Shape`) and passes the `color` argument to it. -- In the Shape class, the defined constructor takes a color as a parameter `protected Shape(string color)`. This means there's no longer a default parameterless constructor automatically provided by C# thus derived classes must use the `: base(color)` expression to invoke the base constructor. Setting the default value to color `protected Shape(string color="green")` will allow to omit the - `: base(color)` expression in derived classes, still such constructor `protected Shape(string color="green")` will be invoked, setting the color to green. +- In the `Shape` class, the defined constructor takes a color as a parameter `protected Shape(string color)`. This means C# no longer provides a default parameterless constructor automatically. Derived classes must use the `: base(color)` expression to invoke the base constructor. Setting the default value to color `protected Shape(string color="green")` allows omitting the `: base(color)` expression in derived classes. The constructor `protected Shape(string color="green")` sets the color to green. + +## C# Language Specification -## C# Language Specification +[!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)] - [!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)] - ## See also - [virtual](./virtual.md) diff --git a/docs/csharp/language-reference/keywords/access-modifiers.md b/docs/csharp/language-reference/keywords/access-modifiers.md index 3e55fd838d60b..be8e75fd79a42 100644 --- a/docs/csharp/language-reference/keywords/access-modifiers.md +++ b/docs/csharp/language-reference/keywords/access-modifiers.md @@ -1,7 +1,7 @@ --- description: "Access Modifiers - C# Reference" title: "Access Modifiers" -ms.date: 12/15/2025 +ms.date: 01/21/2026 helpviewer_keywords: - "access modifiers [C#]" --- @@ -23,6 +23,8 @@ By using these access modifiers, you can specify the following six accessibility - [`private`](private.md): Access is limited to the containing type. - [`private protected`](private-protected.md): Access is limited to the containing class or types derived from the containing class within the current assembly. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + In addition, a top-level (non-nested) type can use the [`file`](file.md) modifier. The declared type is only visible in the current source file. File scoped types are generally used for source generators. You can't combine the `file` modifier with any access modifier. This section also introduces the following concepts: diff --git a/docs/csharp/language-reference/keywords/accessibility-domain.md b/docs/csharp/language-reference/keywords/accessibility-domain.md index 8ff15abba1d32..4b808851763e4 100644 --- a/docs/csharp/language-reference/keywords/accessibility-domain.md +++ b/docs/csharp/language-reference/keywords/accessibility-domain.md @@ -1,27 +1,26 @@ --- description: "Accessibility Domain - C# Reference" title: "Accessibility Domain" -ms.date: 07/20/2015 +ms.date: 01/21/2026 helpviewer_keywords: - "accessibility domain [C#]" -ms.assetid: 8af779c1-275b-44be-a864-9edfbca71bcc --- -# Accessibility Domain (C# Reference) - -The accessibility domain of a member specifies in which program sections a member can be referenced. If the member is nested within another type, its accessibility domain is determined by both the [accessibility level](./accessibility-levels.md) of the member and the accessibility domain of the immediately containing type. - - The accessibility domain of a top-level type is at least the program text of the project that it is declared in. That is, the domain includes all of the source files of this project. The accessibility domain of a nested type is at least the program text of the type in which it is declared. That is, the domain is the type body, which includes all nested types. The accessibility domain of a nested type never exceeds that of the containing type. These concepts are demonstrated in the following example. - -## Example - - This example contains a top-level type, `T1`, and two nested classes, `M1` and `M2`. The classes contain fields that have different declared accessibilities. In the `Main` method, a comment follows each statement to indicate the accessibility domain of each member. Notice that the statements that try to reference the inaccessible members are commented out. If you want to see the compiler errors caused by referencing an inaccessible member, remove the comments one at a time. - -[!code-csharp[csrefKeywordsModifiers#4](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#4)] - -## C# Language Specification - - [!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)] - +# Accessibility domain (C# reference) + +The accessibility domain of a member specifies the program sections where you can reference that member. If the member is nested within another type, both the [accessibility level](./accessibility-levels.md) of the member and the accessibility domain of the immediately containing type determine its accessibility domain. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +The accessibility domain of a top-level type always includes at least the program text of the project where you declare it. In other words, the domain includes all source files in the project. The accessibility domain of a nested type always includes at least the program text of the type where you declare it. In other words, the domain is the type body, which includes all nested types. The accessibility domain of a nested type never exceeds that of the containing type. The following example demonstrates these concepts. + +This example contains a top-level type, `T1`, and two nested classes, `M1` and `M2`. The classes contain fields that have different declared accessibilities. In the `Main` method, a comment follows each statement to indicate the accessibility domain of each member. The statements that try to reference the inaccessible members are commented out. If you want to see the compiler errors caused by referencing an inaccessible member, remove the comments one at a time. + +:::code language="csharp" source="snippets/csrefKeywordsModifiers.cs" id="4"::: + +## C# Language Specification + +[!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)] + ## See also - [C# Keywords](./index.md) diff --git a/docs/csharp/language-reference/keywords/accessibility-levels.md b/docs/csharp/language-reference/keywords/accessibility-levels.md index 759a998970f70..46f89348275fc 100644 --- a/docs/csharp/language-reference/keywords/accessibility-levels.md +++ b/docs/csharp/language-reference/keywords/accessibility-levels.md @@ -1,7 +1,7 @@ --- description: "Accessibility Levels - C# Reference" title: "Accessibility Levels" -ms.date: 12/15/2025 +ms.date: 01/21/2026 helpviewer_keywords: - "access modifiers [C#], accessibility levels" - "accessibility levels" @@ -10,14 +10,14 @@ helpviewer_keywords: Use the access modifiers `public`, `protected`, `internal`, or `private` to specify one of the following declared accessibility levels for members. -| Declared accessibility | Meaning | -|-----------------------------------------------|-------------------------------------------------------------| -| [`public`](public.md) | Access isn't restricted. | -| [`protected`](protected.md) | Access is limited to the containing class or types derived from the containing class. | -| [`internal`](internal.md) | Access is limited to the current assembly. | -| [`protected internal`](protected-internal.md) | Access is limited to the current assembly or types derived from the containing class. | -| [`private`](private.md) | Access is limited to the containing type. | -| [`private protected`](private-protected.md) | Access is limited to the containing class or types derived from the containing class within the current assembly. | +- [`public`](public.md): Access isn't restricted. +- [`protected`](protected.md): Access is limited to the containing class or types derived from the containing class. +- [`internal`](internal.md): Access is limited to the current assembly. +- [`protected internal`](protected-internal.md): Access is limited to the current assembly or types derived from the containing class. +- [`private`](private.md): Access is limited to the containing type. +- [`private protected`](private-protected.md): Access is limited to the containing class or types derived from the containing class within the current assembly. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] Top-level (non-nested) types can use the [file](../../language-reference/keywords/file.md) modifier. The `file` modifier restricts access to code in the same source file. You can't combine the `file` modifier with any access modifier. diff --git a/docs/csharp/language-reference/keywords/add.md b/docs/csharp/language-reference/keywords/add.md index 8c30022d01000..7a5681a9f9b45 100644 --- a/docs/csharp/language-reference/keywords/add.md +++ b/docs/csharp/language-reference/keywords/add.md @@ -1,7 +1,7 @@ --- description: The `add` contextual keyword declares an event accessor that adds a handler to that event. title: "The `add` keyword" -ms.date: 03/13/2025 +ms.date: 01/21/2026 f1_keywords: - "add_CSharpKeyword" helpviewer_keywords: @@ -9,13 +9,15 @@ helpviewer_keywords: --- # The `add` contextual keyword (C# Reference) -The `add` contextual keyword is used to define a custom event accessor that is invoked when client code subscribes to your [event](./event.md). If you supply a custom `add` accessor, you must also supply a [remove](./remove.md) accessor. +Use the `add` contextual keyword to define a custom event accessor that's invoked when client code subscribes to your [event](./event.md). If you supply a custom `add` accessor, you must also supply a [remove](./remove.md) accessor. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] The following example shows an event that has custom `add` and [remove](./remove.md) accessors. For the full example, see [How to implement interface events](../../programming-guide/events/how-to-implement-interface-events.md). :::code language="csharp" source="./snippets/events.cs" id="AddHandler"::: -You don't typically need to provide your own custom event accessors. The automatically generated accessors when you declare an event are sufficient for most scenarios. Beginning with C# 14, you can declare [`partial`](./partial-member.md) events. The implementing declaration of a partial event must declare the `add` and `remove` handlers. +You don't typically need to provide your own custom event accessors. The automatically generated accessors when you declare an event are sufficient for most scenarios. Starting with C# 14, you can declare [`partial`](./partial-member.md) events. The implementing declaration of a partial event must declare the `add` and `remove` handlers. ## See also diff --git a/docs/csharp/language-reference/keywords/ascending.md b/docs/csharp/language-reference/keywords/ascending.md index a75e97802191e..839042116b709 100644 --- a/docs/csharp/language-reference/keywords/ascending.md +++ b/docs/csharp/language-reference/keywords/ascending.md @@ -1,24 +1,23 @@ --- description: "ascending - C# Reference" title: "ascending keyword" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "ascending" - "ascending_CSharpKeyword" helpviewer_keywords: - "ascending keyword [C#]" -ms.assetid: 57fbb619-8187-481c-b68e-3a91996fde69 --- # ascending (C# Reference) -The `ascending` contextual keyword is used in the [orderby clause](./orderby-clause.md) in query expressions to specify that the sort order is from smallest to largest. Because `ascending` is the default sort order, you do not have to specify it. - -## Example +Use the `ascending` contextual keyword in the [orderby clause](./orderby-clause.md) of query expressions to specify that the sort order goes from smallest to largest. Because `ascending` is the default sort order, you don't need to specify it. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +The following example shows how to use `ascending` in an [orderby clause](./orderby-clause.md). + +:::code language="csharp" source="./snippets/csrefKeywordsContextual.cs" id="14"::: - The following example shows the use of `ascending` in an [orderby clause](./orderby-clause.md). - -[!code-csharp[csrefKeywordsContextual#14](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/csrefKeywordsContextual.cs#14)] - ## See also - [LINQ in C#](../../linq/index.md) diff --git a/docs/csharp/language-reference/keywords/async.md b/docs/csharp/language-reference/keywords/async.md index a65193cbd47ca..7050eee57e4a7 100644 --- a/docs/csharp/language-reference/keywords/async.md +++ b/docs/csharp/language-reference/keywords/async.md @@ -1,19 +1,18 @@ --- description: "async - C# Reference" title: "async keyword" -ms.date: 05/22/2017 +ms.date: 01/21/2026 f1_keywords: - "async_CSharpKeyword" helpviewer_keywords: - "async keyword [C#]" - "async method [C#]" - "async [C#]" -ms.assetid: 16f14f09-b2ce-42c7-a875-e4eca5d50674 --- -# async (C# Reference) +# async (C# reference) -Use the `async` modifier to specify that a method, [lambda expression](../operators/lambda-expressions.md), or [anonymous method](../operators/delegate-operator.md) is asynchronous. If you use this modifier on a method or expression, it's referred to as an *async method*. The following example defines an async method named `ExampleMethodAsync`: +Use the `async` modifier to specify that a method, [lambda expression](../operators/lambda-expressions.md), or [anonymous method](../operators/delegate-operator.md) is asynchronous. If you use this modifier on a method or expression, you create an *async method*. The following example defines an async method named `ExampleMethodAsync`: ```csharp public async Task ExampleMethodAsync() @@ -22,21 +21,21 @@ public async Task ExampleMethodAsync() } ``` -If you're new to asynchronous programming or do not understand how an async method uses the [`await` operator](../operators/await.md) to do potentially long-running work without blocking the caller's thread, read the introduction in [Asynchronous programming with async and await](../../asynchronous-programming/index.md). The following code is found inside an async method and calls the method: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +If you're new to asynchronous programming or don't understand how an async method uses the [`await` operator](../operators/await.md) to do potentially long-running work without blocking the caller's thread, read the introduction in [Asynchronous programming with async and await](../../asynchronous-programming/index.md). The following code is found inside an async method and calls the method: ```csharp string contents = await httpClient.GetStringAsync(requestUrl); ``` -An async method runs synchronously until it reaches its first `await` expression, at which point the method is suspended until the awaited task is complete. In the meantime, control returns to the caller of the method, as the example in the next section shows. +An async method runs synchronously until it reaches its first `await` expression. At that point, the method is suspended until the awaited task is complete. In the meantime, control returns to the caller of the method, as the example in the next section shows. If the method that the `async` keyword modifies doesn't contain an `await` expression or statement, the method executes synchronously. A compiler warning alerts you to any async methods that don't contain `await` statements, because that situation might indicate an error. See [Compiler Warning (level 1) CS4014](../compiler-messages/async-await-errors.md#async-practices). - The `async` keyword is contextual in that it's a keyword only when it modifies a method, a lambda expression, or an anonymous method. In all other contexts, it's interpreted as an identifier. - -## Example + The `async` keyword is contextual. It's a keyword only when it modifies a method, a lambda expression, or an anonymous method. In all other contexts, the compiler interprets it as an identifier. -The following example shows the structure and flow of control between an async event handler, `StartButton_Click`, and an async method, `ExampleMethodAsync`. The result from the async method is the number of characters of a web page. The code is suitable for a Windows Presentation Foundation (WPF) app or Windows Store app that you create in Visual Studio; see the code comments for setting up the app. +The following example shows the structure and flow of control between an async event handler, `StartButton_Click`, and an async method, `ExampleMethodAsync`. The result from the async method is the number of characters of a web page. The code is suitable for a Windows Presentation Foundation (WPF) app or Windows Store app that you create in Visual Studio. See the code comments for setting up the app. You can run this code in Visual Studio as a Windows Presentation Foundation (WPF) app or a Windows Store app. You need a Button control named `StartButton` and a Textbox control named `ResultsTextBox`. Remember to set the names and handler so that you have something like this: @@ -58,27 +57,23 @@ To run the code as a Windows Store app: - Paste this code into the `MainPage` class in MainPage.xaml.cs. - Add `using` directives for System.Net.Http and System.Threading.Tasks. -[!code-csharp[wpf-async](../../../../samples/snippets/csharp/language-reference/keywords/async/wpf/MainWindow.xaml.cs#1)] +:::code language="csharp" source="./snippets/async/wpf/MainWindow.xaml.cs" id="1"::: > [!IMPORTANT] > For more information about tasks and the code that executes while waiting for a task, see [Asynchronous programming with async and await](../../asynchronous-programming/index.md). For a full console example that uses similar elements, see [Process asynchronous tasks as they complete (C#)](../../asynchronous-programming/start-multiple-async-tasks-and-process-them-as-they-complete.md). -## Return Types +## Return types An async method can have the following return types: - - -- [void](../builtin-types/void.md). `async void` methods are generally discouraged for code other than event handlers because callers cannot `await` those methods and must implement a different mechanism to report successful completion or error conditions. -- Any type that has an accessible `GetAwaiter` method. The `System.Threading.Tasks.ValueTask` type is one such implementation. It is available by adding the NuGet package `System.Threading.Tasks.Extensions`. - -The async method can't declare any [in](method-parameters.md#in-parameter-modifier), [ref](./ref.md) or [out](method-parameters.md#out-parameter-modifier) parameters, nor can it have a [reference return value](../statements/jump-statements.md#ref-returns), but it can call methods that have such parameters. - -You specify `Task` as the return type of an async method if the [return](../statements/jump-statements.md#the-return-statement) statement of the method specifies an operand of type `TResult`. You use `Task` if no meaningful value is returned when the method is completed. That is, a call to the method returns a `Task`, but when the `Task` is completed, any `await` expression that's awaiting the `Task` evaluates to `void`. +- [`void`](../builtin-types/void.md). Generally, avoid using `async void` methods for code other than event handlers because callers can't `await` those methods and must implement a different mechanism to report successful completion or error conditions. +- Any type that has an accessible `GetAwaiter` method. The `System.Threading.Tasks.ValueTask` type is one such implementation. It's available by adding the NuGet package `System.Threading.Tasks.Extensions`. -You use the `void` return type primarily to define event handlers, which require that return type. The caller of a `void`-returning async method can't await it and can't catch exceptions that the method throws. +The async method can't declare any [`in`](method-parameters.md#in-parameter-modifier), [`ref`](./ref.md), [`ref readonly`](./ref.md), or [`out`](method-parameters.md#out-parameter-modifier) parameters, nor can it have a [reference return value](../statements/jump-statements.md#ref-returns). However, it can call methods that have such parameters. -You return another type, typically a value type, that has a `GetAwaiter` method to minimize memory allocations in performance-critical sections of code. +Specify `Task` as the return type of an async method if the [return](../statements/jump-statements.md#the-return-statement) statement of the method specifies an operand of type `TResult`. Use `Task` if the method returns no meaningful value when it completes. That is, a call to the method returns a `Task`, but when the `Task` is completed, any `await` expression that's awaiting the `Task` evaluates to `void`. Use the `void` return type primarily to define event handlers, which require that return type. The caller of a `void`-returning async method can't await it and can't catch exceptions that the method throws. Return another type, typically a value type, that has a `GetAwaiter` method to minimize memory allocations in performance-critical sections of code. For more information and examples, see [Async Return Types](../../asynchronous-programming/async-return-types.md). diff --git a/docs/csharp/language-reference/keywords/base.md b/docs/csharp/language-reference/keywords/base.md index b6395a0ce636a..fcbdee7f6b6e3 100644 --- a/docs/csharp/language-reference/keywords/base.md +++ b/docs/csharp/language-reference/keywords/base.md @@ -1,7 +1,7 @@ --- title: "The base keyword" description: Learn about the base keyword, which is used to access members of the base class from within a derived class in C#. -ms.date: 04/17/2025 +ms.date: 01/21/2026 f1_keywords: - "base" - "BaseClass.BaseClass" @@ -11,20 +11,22 @@ helpviewer_keywords: --- # The base keyword -The `base` keyword is used to access members of the base class from within a derived class. Use it if you want to: +Use the `base` keyword to access members of the base class from within a derived class. Use it if you want to: -- Call a method on the base class overridden by another method. -- Specify which base-class constructor should be called when creating instances of the derived class. +- Call a method on the base class that's overridden by another method. +- Specify which base-class constructor to call when creating instances of the derived class. -The base class access is permitted only in a constructor, in an instance method, and in an instance property accessor. Using the `base` keyword from within a static method produces an error. +You can access the base class only in a constructor, in an instance method, and in an instance property accessor. Using the `base` keyword from within a static method produces an error. -The base class that is accessed is the base class specified in the class declaration. For example, if you specify `class ClassB : ClassA`, the members of ClassA are accessed from ClassB, regardless of the base class of ClassA. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -In this example, both the base class `Person` and the derived class `Employee` have a method named `GetInfo`. By using the `base` keyword, it's possible to call the `GetInfo` method of the base class from within the derived class. +The base class you access is the base class you specify in the class declaration. For example, if you specify `class ClassB : ClassA`, you access the members of ClassA from ClassB, regardless of the base class of ClassA. + +In this example, both the base class `Person` and the derived class `Employee` have a method named `GetInfo`. By using the `base` keyword, you can call the `GetInfo` method of the base class from within the derived class. :::code language="csharp" source="./snippets/csrefKeywordsAccess.cs" id="snippet1"::: -This example shows how to specify the base-class constructor called when creating instances of a derived class. +This example shows how to specify the base-class constructor to call when creating instances of a derived class. :::code language="csharp" source="./snippets/csrefKeywordsAccess.cs" id="snippet2"::: diff --git a/docs/csharp/language-reference/keywords/by.md b/docs/csharp/language-reference/keywords/by.md index e8fe60bf234e7..cb7734c6532d6 100644 --- a/docs/csharp/language-reference/keywords/by.md +++ b/docs/csharp/language-reference/keywords/by.md @@ -1,23 +1,22 @@ --- description: "by contextual keyword - C# Reference" title: "by contextual keyword" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "by" - "by_CSharpKeyword" helpviewer_keywords: - "by keyword [C#]" -ms.assetid: efe6f0e3-be40-4df2-a144-c7db968ae052 --- # by (C# Reference) -The `by` contextual keyword is used in the `group` clause in a query expression to specify how the returned items should be grouped. For more information, see [group clause](./group-clause.md). +Use the `by` contextual keyword in the `group` clause of a query expression to specify how to group the returned items. For more information, see [group clause](./group-clause.md). -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -The following example shows the use of the `by` contextual keyword in a `group` clause to specify that the students should be grouped according to the first letter of the last name of each student. +The following example shows how to use the `by` contextual keyword in a `group` clause to group students by the first letter of each student's last name. -[!code-csharp[csrefKeywordsContextual#10](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/csrefKeywordsContextual.cs#10)] +:::code language="csharp" source="./snippets/csrefKeywordsContextual.cs" id="10"::: ## See also diff --git a/docs/csharp/language-reference/keywords/class.md b/docs/csharp/language-reference/keywords/class.md index 3a190ccf98a1d..90905cf16bb98 100644 --- a/docs/csharp/language-reference/keywords/class.md +++ b/docs/csharp/language-reference/keywords/class.md @@ -1,17 +1,16 @@ --- description: "class keyword - C# Reference" title: "class keyword" -ms.date: 07/18/2017 +ms.date: 01/21/2026 f1_keywords: - "class_CSharpKeyword" - "class" helpviewer_keywords: - "class keyword [C#]" -ms.assetid: b95d8815-de18-4c3f-a8cc-a0a53bdf8690 --- # class (C# Reference) -Classes are declared using the keyword `class`, as shown in the following example: +Declare classes by using the `class` keyword, as shown in the following example: ```csharp class TestClass @@ -21,20 +20,15 @@ class TestClass } ``` -## Remarks +C# supports only single inheritance. In other words, a class can inherit implementation from one base class only. However, a class can implement more than one interface. -Only single inheritance is allowed in C#. In other words, a class can inherit implementation from one base class only. However, a class can implement more than one interface. The following table shows examples of class inheritance and interface implementation: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -|Inheritance|Example| -|-----------------|-------------| -|None|`class ClassA { }`| -|Single|`class DerivedClass : BaseClass { }`| -|None, implements two interfaces|`class ImplClass : IFace1, IFace2 { }`| -|Single, implements one interface|`class ImplDerivedClass : BaseClass, IFace1 { }`| +For more information on classes, interfaces, and inheritance see the article on [inheritance](../../fundamentals/object-oriented/inheritance.md) in the fundamentals section. -Classes that you declare directly within a namespace, not nested within other classes, can be either [public](./public.md) or [internal](./internal.md). Classes are `internal` by default. +You can declare classes directly within a namespace. Don't nest these classes within other classes. You can make these classes either [`public`](./public.md) or [`internal`](./internal.md). By default, classes are `internal`. -Class members, including nested classes, can be [public](public.md), [protected internal](protected-internal.md), [protected](protected.md), [internal](internal.md), [private](private.md), or [private protected](private-protected.md). Members are `private` by default. +You can declare class members, including nested classes, as [`public`](public.md), [`protected internal`](protected-internal.md), [`protected`](protected.md), [`internal`](internal.md), [`private`](private.md), or [`private protected`](private-protected.md). By default, members are `private`. For more information, see [Access Modifiers](../../programming-guide/classes-and-structs/access-modifiers.md). @@ -43,52 +37,35 @@ You can declare generic classes that have type parameters. For more information, A class can contain declarations of the following members: - [Constructors](../../programming-guide/classes-and-structs/constructors.md) - - [Constants](../../programming-guide/classes-and-structs/constants.md) - - [Fields](../../programming-guide/classes-and-structs/fields.md) - - [Finalizers](../../programming-guide/classes-and-structs/finalizers.md) - - [Methods](../../programming-guide/classes-and-structs/methods.md) - - [Properties](../../programming-guide/classes-and-structs/properties.md) - - [Indexers](../../programming-guide/indexers/index.md) - - [Operators](../operators/index.md) - - [Events](../../programming-guide/events/index.md) - - [Delegates](../../programming-guide/delegates/index.md) - - [Classes](../../fundamentals/types/classes.md) - - [Interfaces](../../fundamentals/types/interfaces.md) - - [Structure types](../builtin-types/struct.md) - - [Enumeration types](../builtin-types/enum.md) ## Example -The following example demonstrates declaring class fields, constructors, and methods. It also demonstrates object instantiation and printing instance data. In this example, two classes are declared. The first class, `Child`, contains two private fields (`name` and `age`), two public constructors and one public method. The second class, `StringTest`, is used to contain `Main`. +The following example demonstrates declaring class fields, constructors, and methods. It also demonstrates object instantiation and printing instance data. In this example, two classes are declared. The first class, `Child`, contains two private fields (`name` and `age`), two public constructors, and one public method. The second class, `StringTest`, contains `Main`. -[!code-csharp[csrefKeywordsTypes#5](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsTypes/CS/keywordsTypes.cs#5)] +:::code language="csharp" source="./snippets/keywordsTypes.cs" id="5"::: ## Comments -Notice that in the previous example the private fields (`name` and `age`) can only be accessed through the public method of the `Child` class. For example, you cannot print the child's name, from the `Main` method, using a statement like this: +You can only access the private fields (`name` and `age`) through the public method of the `Child` class. For example, you can't print the child's name from the `Main` method by using a statement like this: ```csharp Console.Write(child1.name); // Error ``` -Accessing private members of `Child` from `Main` would only be possible if `Main` were a member of the class. - -Types declared inside a class without an access modifier default to `private`, so the data members in this example would still be `private` if the keyword were removed. - -Finally, notice that for the object created using the parameterless constructor (`child3`), the `age` field was initialized to zero by default. +Accessing private members of `Child` from `Main` is only possible if `Main` is a member of the class. Types declared inside a class without an access modifier default to `private`, so the data members in this example are still `private` if the keyword is removed. Finally, for the object created by using the parameterless constructor (`child3`), the `age` field is initialized to zero by default. ## C# language specification diff --git a/docs/csharp/language-reference/keywords/const.md b/docs/csharp/language-reference/keywords/const.md index 6cf386a436395..29d0e51fdf5cd 100644 --- a/docs/csharp/language-reference/keywords/const.md +++ b/docs/csharp/language-reference/keywords/const.md @@ -1,7 +1,7 @@ --- description: "Declare compile time constants with the `const` keyword" title: "The const keyword" -ms.date: 11/22/2024 +ms.date: 01/21/2026 f1_keywords: - "const_CSharpKeyword" - "const" @@ -10,7 +10,7 @@ helpviewer_keywords: --- # The const keyword -You use the `const` keyword to declare a constant field or a local constant. Constant fields and locals aren't variables and can't be modified. Constants can be numbers, Boolean values, strings, or a null reference. Don’t create a constant to represent information that you expect to change at any time. For example, don’t use a constant field to store the price of a service, a product version number, or the brand name of a company. These values can change over time, and because compilers propagate constants, other code compiled with your libraries will have to be recompiled to see the changes. See also the [readonly](readonly.md) keyword. For example: +Use the `const` keyword to declare a constant field or a local constant. Constant fields and locals aren't variables and can't be modified. Constants can be numbers, Boolean values, strings, or a null reference. Don't create a constant to represent information that you expect to change over time. For example, don't use a constant field to store the price of a service, a product version number, or the brand name of a company. These values can change over time, and because compilers propagate constants, other code compiled with your libraries needs to be recompiled to see the changes. See also the [readonly](readonly.md) keyword. For example: ```csharp const int X = 0; @@ -18,7 +18,7 @@ public const double GravitationalConstant = 6.673e-11; private const string ProductName = "Visual C#"; ``` -[Interpolated strings](../tokens/interpolated.md) can be constants, if all expressions used are also constant strings. This feature can improve the code that builds constant strings: +[Interpolated strings](../tokens/interpolated.md) can be constants if all expressions used are also constant strings. This feature can improve the code that builds constant strings: ```csharp const string Language = "C#"; @@ -26,13 +26,13 @@ const string Platform = ".NET"; const string FullProductName = $"{Platform} - Language: {Language}"; ``` -## Remarks +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -The type of a constant declaration specifies the type of the members that the declaration introduces. The initializer of a local constant or a constant field must be a constant expression that can be implicitly converted to the target type. +The type of a constant declaration specifies the type of the members that the declaration introduces. The initializer of a local constant or a constant field must be a constant expression that the compiler can implicitly convert to the target type. -A constant expression is an expression that can be fully evaluated at compile time. Therefore, the only possible values for constants of reference types are strings and a null reference. +A constant expression is an expression that the compiler can fully evaluate at compile time. Therefore, the only possible values for constants of reference types are strings and a null reference. -The constant declaration can declare multiple constants, such as: +You can declare multiple constants in a single constant declaration, such as: ```csharp public const double X = 1.0, Y = 2.0, Z = 3.0; @@ -48,15 +48,15 @@ public const int C2 = C1 + 100; ``` > [!NOTE] -> The [readonly](readonly.md) keyword differs from the `const` keyword. A `const` field can only be initialized at the declaration of the field. A `readonly` field can be initialized either at the declaration or in a constructor. Therefore, `readonly` fields can have different values depending on the constructor used. Also, although a `const` field is a compile-time constant, the `readonly` field can be used for run-time constants, as in this line: `public static readonly uint l1 = (uint)DateTime.Now.Ticks;` +> The [readonly](readonly.md) keyword differs from the `const` keyword. You can only initialize a `const` field at the declaration of the field. You can initialize a `readonly` field either at the declaration or in a constructor. Therefore, `readonly` fields can have different values depending on the constructor used. Also, although a `const` field is a compile-time constant, the `readonly` field can be used for run-time constants, as in this line: `public static readonly uint l1 = (uint)DateTime.Now.Ticks;` ## Examples -[!code-csharp[csrefKeywordsModifiers#5](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#5)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="5"::: -The following example demonstrates how to declare a local constant: +The following example shows how to declare a local constant: -[!code-csharp[csrefKeywordsModifiers#6](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#6)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="6"::: ## C# language specification diff --git a/docs/csharp/language-reference/keywords/default.md b/docs/csharp/language-reference/keywords/default.md index 82b0d31adf167..1918cbf1eb5d8 100644 --- a/docs/csharp/language-reference/keywords/default.md +++ b/docs/csharp/language-reference/keywords/default.md @@ -1,22 +1,23 @@ --- description: "default - C# reference" title: "default keyword" -ms.date: 04/28/2021 +ms.date: 01/21/2026 f1_keywords: - "default" helpviewer_keywords: - "default keyword [C#]" -ms.assetid: 14c48aaa-7d35-4058-a1a4-f53353050579 --- # default (C# reference) -You can use the `default` keyword in the following contexts: +Use the `default` keyword in the following contexts: - To specify the default case in the [`switch` statement](../statements/selection-statements.md#the-switch-statement). - As the [default operator or literal](../operators/default.md) to produce the default value of a type. - As the [`default` type constraint](where-generic-type-constraint.md) on a generic method override or explicit interface implementation. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + ## See also - [C# keywords](index.md) diff --git a/docs/csharp/language-reference/keywords/descending.md b/docs/csharp/language-reference/keywords/descending.md index 9c48aaffb8e6f..e4e70350f600c 100644 --- a/docs/csharp/language-reference/keywords/descending.md +++ b/docs/csharp/language-reference/keywords/descending.md @@ -1,23 +1,22 @@ --- description: "descending contextual keyword - C# Reference" title: "descending contextual keyword" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "descending" - "descending_CSharpKeyword" helpviewer_keywords: - "descending keyword [C#]" -ms.assetid: 8d2cd1e5-9c1c-4dfc-b84c-60e2d3240927 --- # descending (C# Reference) -The `descending` contextual keyword is used in the [orderby clause](./orderby-clause.md) in query expressions to specify that the sort order is from largest to smallest. +Use the `descending` contextual keyword in the [orderby clause](./orderby-clause.md) of query expressions to specify that the sort order is from largest to smallest. -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -The following example shows the use of `descending` in an [orderby clause](./orderby-clause.md). +The following example shows how to use `descending` in an [orderby clause](./orderby-clause.md). -[!code-csharp[csrefKeywordsContextual#11](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/csrefKeywordsContextual.cs#11)] +:::code language="csharp" source="./snippets/csrefKeywordsContextual.cs" id="11"::: ## See also diff --git a/docs/csharp/language-reference/keywords/equals.md b/docs/csharp/language-reference/keywords/equals.md index 1918cf6591434..085dc5b7c5b0d 100644 --- a/docs/csharp/language-reference/keywords/equals.md +++ b/docs/csharp/language-reference/keywords/equals.md @@ -1,23 +1,22 @@ --- description: "equals contextual keyword - C# Reference" title: "equals contextual keyword" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "equals_CSharpKeyword" - "equals" helpviewer_keywords: - "equals keyword [C#]" -ms.assetid: e981309a-e4bf-444c-8a2b-5c695e6114b1 --- # equals (C# Reference) -The `equals` contextual keyword is used in a `join` clause in a query expression to compare the elements of two sequences. For more information, see [join clause](join-clause.md). +Use the `equals` contextual keyword in a `join` clause of a query expression to compare the elements of two sequences. For more information, see [join clause](join-clause.md). -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -The following example shows the use of the `equals` keyword in a `join` clause. +The following example shows how to use the `equals` keyword in a `join` clause. -[!code-csharp[csrefKeywordsContextual#12](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/csrefKeywordsContextual.cs#12)] +:::code language="csharp" source="./snippets/csrefKeywordsContextual.cs" id="12"::: ## See also diff --git a/docs/csharp/language-reference/keywords/event.md b/docs/csharp/language-reference/keywords/event.md index f0d6f77815670..ec8cbaac31fc8 100644 --- a/docs/csharp/language-reference/keywords/event.md +++ b/docs/csharp/language-reference/keywords/event.md @@ -1,7 +1,7 @@ --- description: "Learn how to declare events with the `event` keyword - C# Reference" title: "The `event` keyword" -ms.date: 03/13/2025 +ms.date: 01/21/2026 f1_keywords: - "event" - "remove" @@ -14,30 +14,30 @@ helpviewer_keywords: An ***event*** is a member that enables an object to trigger notifications. Event users can attach executable code for events by supplying ***event handlers***. The `event` keyword declares an ***event***. The event is of a delegate type. While an object triggers an event, the event invokes all supplied event handlers. Event handlers are delegate instances added to the event and executed when the event is raised. Event users can add or remove their event handlers on an event. -The following example shows how to declare and raise an event that uses as the underlying delegate type. For the complete code example, see [How to publish events that conform to .NET Guidelines](/dotnet/standard/events). That sample demonstrates the generic delegate type, how to subscribe to an event, and create an event handler method, +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +The following example shows how to declare and raise an event that uses as the underlying delegate type. For the complete code example, see [How to publish events that conform to .NET Guidelines](/dotnet/standard/events). That sample demonstrates the generic delegate type, how to subscribe to an event, and create an event handler method. :::code language="csharp" source="./snippets/Events.cs" id="EventExample"::: -Events are multicast delegates that can only be invoked from within the class (or derived classes) or struct where they're declared (the publisher class). If other classes or structs subscribe to the event, their event handler methods are called when the publisher class raises the event. For more information and code examples, see [Events](../../programming-guide/events/index.md) and [Delegates](../../programming-guide/delegates/index.md). +Events are multicast delegates that you can only invoke from within the class (or derived classes) or struct where you declare them (the publisher class). If other classes or structs subscribe to the event, their event handler methods are called when the publisher class raises the event. For more information and code examples, see [Events](../../programming-guide/events/index.md) and [Delegates](../../programming-guide/delegates/index.md). -Events can be marked as [`public`](./public.md), [`private`](./private.md), [`protected`](./protected.md), [`internal`](./internal.md), [`protected internal`](./protected-internal.md), or [`private protected`](./private-protected.md). These access modifiers define how users of the class can access the event. For more information, see [Access Modifiers](../../programming-guide/classes-and-structs/access-modifiers.md). +You can mark events as [`public`](./public.md), [`private`](./private.md), [`protected`](./protected.md), [`internal`](./internal.md), [`protected internal`](./protected-internal.md), or [`private protected`](./private-protected.md). These access modifiers define how users of the class can access the event. For more information, see [Access Modifiers](../../programming-guide/classes-and-structs/access-modifiers.md). -Beginning with C# 14, events can be [`partial`](./partial-member.md). Partial events have one defining declaration and one implementing declaration. The defining declaration must use the field-like syntax. The implementing declaration must declare the `add` and `remove` handlers. +Starting with C# 14, you can declare events as [`partial`](./partial-member.md). Partial events have one defining declaration and one implementing declaration. The defining declaration must use the field-like syntax. The implementing declaration must declare the `add` and `remove` handlers. ## Keywords and events The following keywords apply to events. -| Keyword | Description | For more information | -|---------------------------|-----------------|----------------------| -| [`static`](./static.md) | Makes the event available to callers at any time, even if no instance of the class exists. | [Static Classes and Static Class Members](../../programming-guide/classes-and-structs/static-classes-and-static-class-members.md) | -| [`virtual`](./virtual.md) | Allows derived classes to override the event behavior by using the [override](./override.md) keyword. | [Inheritance](../../fundamentals/object-oriented/inheritance.md)| -| [`sealed`](./sealed.md) | Specifies that for derived classes it's no longer virtual. | | -| [`abstract`](./abstract.md) | The compiler doesn't generate the `add` and `remove` event accessor blocks and therefore derived classes must provide their own implementation. | | +- [`static`](./static.md): Makes the event available to callers at any time, even if no instance of the class exists. For more information on static events, see [Static Classes and Static Class Members](../../programming-guide/classes-and-structs/static-classes-and-static-class-members.md). +- [`virtual`](./virtual.md): Allows derived classes to override the event behavior by using the [override](./override.md) keyword. For more information on virtual events, see [Inheritance](../../fundamentals/object-oriented/inheritance.md). +- [`sealed`](./sealed.md): Specifies that for derived classes it's no longer virtual. +- [`abstract`](./abstract.md): The compiler doesn't generate the `add` and `remove` event accessor blocks and therefore derived classes must provide their own implementation. -An event can be declared as a static event by using the [static](./static.md) keyword. Static events are available to callers at any time, even if no instance of the class exists. For more information, see [Static Classes and Static Class Members](../../programming-guide/classes-and-structs/static-classes-and-static-class-members.md). +Use the [`static`](./static.md) keyword to declare an event as a static event. Static events are available to callers at any time, even if no instance of the class exists. For more information, see [Static Classes and Static Class Members](../../programming-guide/classes-and-structs/static-classes-and-static-class-members.md). -An event can be marked as a virtual event by using the [`virtual`](./virtual.md) keyword. Derived classes can override the event behavior by using the [`override`](./override.md) keyword. For more information, see [Inheritance](../../fundamentals/object-oriented/inheritance.md). An event overriding a virtual event can also be [`sealed`](./sealed.md), which specifies that for derived classes it's no longer virtual. Lastly, an event can be declared [`abstract`](./abstract.md), which means that the compiler doesn't generate the `add` and `remove` event accessor blocks. Therefore derived classes must provide their own implementation. +Use the [`virtual`](./virtual.md) keyword to mark an event as a virtual event. Derived classes can override the event behavior by using the [`override`](./override.md) keyword. For more information, see [Inheritance](../../fundamentals/object-oriented/inheritance.md). An event overriding a virtual event can also be [`sealed`](./sealed.md), which specifies that for derived classes it's no longer virtual. Lastly, an event can be declared [`abstract`](./abstract.md), which means that the compiler doesn't generate the `add` and `remove` event accessor blocks. Therefore, derived classes must provide their own implementation. ## C# language specification diff --git a/docs/csharp/language-reference/keywords/extension.md b/docs/csharp/language-reference/keywords/extension.md index 4fedb86029700..bd845fc91f1b2 100644 --- a/docs/csharp/language-reference/keywords/extension.md +++ b/docs/csharp/language-reference/keywords/extension.md @@ -1,7 +1,7 @@ --- title: "Extension member declarations" description: "Learn the syntax to declare extension members in C#. Extension members enable you to add functionality to types and interfaces in those instances where you don't have the source for the original type. Extensions are often paired with generic interfaces to implement a common set of functionality across all types that implement that interface." -ms.date: 12/11/2025 +ms.date: 01/21/2026 f1_keywords: - "extension_CSharpKeyword" - "extension" @@ -10,6 +10,8 @@ f1_keywords: Starting with C# 14, top-level, nongeneric `static class` declarations can use `extension` blocks to declare *extension members*. Extension members are methods or properties and can appear to be instance or static members. Earlier versions of C# enable *extension methods* by adding `this` as a modifier to the first parameter of a static method declared in a top-level, nongeneric static class. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + The `extension` block specifies the type and receiver for extension members. You can declare methods, properties, or operators inside the `extension` declaration. The following example declares a single extension block that defines an instance extension method, an instance property, and a static operator method. > [!NOTE] diff --git a/docs/csharp/language-reference/keywords/extern-alias.md b/docs/csharp/language-reference/keywords/extern-alias.md index 979e31e62911b..d408f37f17214 100644 --- a/docs/csharp/language-reference/keywords/extern-alias.md +++ b/docs/csharp/language-reference/keywords/extern-alias.md @@ -1,63 +1,68 @@ --- description: "extern alias - C# Reference" title: "extern alias" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "alias_CSharpKeyword" helpviewer_keywords: - "extern alias keyword [C#]" - "aliases [C#], extern keyword" - "aliases, extern keyword" -ms.assetid: f487bf4f-c943-4fca-851b-e540c83d9027 --- # extern alias (C# Reference) -You might have to reference two versions of assemblies that have the same fully-qualified type names. For example, you might have to use two or more versions of an assembly in the same application. By using an external assembly alias, the namespaces from each assembly can be wrapped inside root-level namespaces named by the alias, which enables them to be used in the same file. - +You might need to reference two versions of assemblies that have the same fully qualified type names. For example, you might need to use two or more versions of an assembly in the same application. By using an external assembly alias, you can wrap the namespaces from each assembly inside root-level namespaces named by the alias. This approach enables you to use both versions in the same file. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + > [!NOTE] -> The [extern](./extern.md) keyword is also used as a method modifier, declaring a method written in unmanaged code. - - To reference two assemblies with the same fully-qualified type names, an alias must be specified at a command prompt, as follows: - - `/r:GridV1=grid.dll` - - `/r:GridV2=grid20.dll` - - This creates the external aliases `GridV1` and `GridV2`. To use these aliases from within a program, reference them by using the `extern` keyword. For example: - - `extern alias GridV1;` - - `extern alias GridV2;` - - Each extern alias declaration introduces an additional root-level namespace that parallels (but does not lie within) the global namespace. Thus types from each assembly can be referred to without ambiguity by using their fully qualified name, rooted in the appropriate namespace-alias. - - In the previous example, `GridV1::Grid` would be the grid control from `grid.dll`, and `GridV2::Grid` would be the grid control from `grid20.dll`. +> The [extern](./extern.md) keyword is also used as a method modifier, declaring a method written in unmanaged code. + +To reference two assemblies with the same fully qualified type names, specify an alias in your *.csproj* file, and add the following code: + +```xml + + GridV1 + + + GridV2 + +``` + +You can learn more in the article on the [CSC task](/visualstudio/msbuild/csc-task) in the Visual Studio documentation. + +This command creates the external aliases `GridV1` and `GridV2`. To use these aliases from within a program, reference them by using the `extern` keyword. For example: +`extern alias GridV1;` +`extern alias GridV2;` + +Each extern alias declaration introduces an additional root-level namespace that parallels (but doesn't lie within) the global namespace. You can refer to types from each assembly without ambiguity by using their fully qualified name, rooted in the appropriate namespace-alias. + +In the previous example, `GridV1::Grid` is the grid control from `grid.dll`, and `GridV2::Grid` is the grid control from `grid20.dll`. + ## Using Visual Studio -If you are using Visual Studio, aliases can be provided in similar way. +If you're using Visual Studio, you can provide aliases in a similar way. -Add reference of *grid.dll* and *grid20.dll* to your project in Visual Studio. Open a property tab and change the Aliases from global to GridV1 and GridV2 respectively. +Add references to *grid.dll* and *grid20.dll* to your project in Visual Studio. Open the property tab and change the **Aliases** from `global` to `GridV1` and `GridV2` respectively. -Use these aliases the same way above +Use these aliases the same way as described earlier. ```csharp - extern alias GridV1; - - extern alias GridV2; +extern alias GridV1; +extern alias GridV2; ``` -Now you can create alias for a namespace or a type by *using alias directive*. For more information, see [using directive](using-directive.md). +Now you can create an alias for a namespace or a type by using the *using alias directive*. For more information, see [using directive](using-directive.md). ```csharp using Class1V1 = GridV1::Namespace.Class1; - using Class1V2 = GridV2::Namespace.Class1; ``` ## C# Language Specification - [!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)] +[!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)] ## See also diff --git a/docs/csharp/language-reference/keywords/extern.md b/docs/csharp/language-reference/keywords/extern.md index 066e507f53df2..a7fa8b830ff9f 100644 --- a/docs/csharp/language-reference/keywords/extern.md +++ b/docs/csharp/language-reference/keywords/extern.md @@ -1,37 +1,34 @@ --- description: "extern modifier - C# Reference" title: "extern modifier" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "extern_CSharpKeyword" - "extern" helpviewer_keywords: - "DllImport attribute" - "extern keyword [C#]" -ms.assetid: 9c3f02c4-51b8-4d80-9cb2-f2b6e1ae15c7 --- # extern (C# Reference) -The `extern` modifier is used to declare a method that is implemented externally. A common use of the `extern` modifier is with the `DllImport` attribute when you are using Interop services to call into unmanaged code. In this case, the method must also be declared as `static`, as shown in the following example: +Use the `extern` modifier to declare a method that's implemented externally. A common use of the `extern` modifier is with the `DllImport` attribute when you use Interop services to call into unmanaged code. In this case, you must also declare the method as `static`, as shown in the following example: ```csharp [DllImport("avifil32.dll")] private static extern void AVIFileInit(); ``` -The `extern` keyword can also define an external assembly alias, which makes it possible to reference different versions of the same component from within a single assembly. For more information, see [extern alias](extern-alias.md). +You can also use the `extern` keyword to define an external assembly alias. By using this alias, you can reference different versions of the same component from within a single assembly. For more information, see [extern alias](extern-alias.md). -It is an error to use the [abstract](abstract.md) and `extern` modifiers together to modify the same member. Using the `extern` modifier means that the method is implemented outside the C# code, whereas using the `abstract` modifier means that the method implementation is not provided in the class. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -The extern keyword has more limited uses in C# than in C++. To compare the C# keyword with the C++ keyword, see [Using extern to Specify Linkage](/cpp/cpp/extern-cpp#extern-c-and-extern-c-function-declarations) in the C++ Language Reference. +It's an error to use the [abstract](abstract.md) and `extern` modifiers together to modify the same member. Using the `extern` modifier means that the method is implemented outside the C# code, whereas using the `abstract` modifier means that the method implementation isn't provided in the class. -## Example 1 +The `extern` keyword has more limited uses in C# than in C++. To compare the C# keyword with the C++ keyword, see [Using extern to Specify Linkage](/cpp/cpp/extern-cpp#extern-c-and-extern-c-function-declarations) in the C++ Language Reference. In this example, the program receives a string from the user and displays it inside a message box. The program uses the `MessageBox` method imported from the User32.dll library. -[!code-csharp[csrefKeywordsModifiers#8](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#8)] - -## Example 2 +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="8"::: This example illustrates a C# program that calls into a C library (a native DLL). @@ -46,9 +43,9 @@ This example illustrates a C# program that calls into a C library (a native DLL) } ``` -2. Open a Visual Studio x64 (or x32) Native Tools Command Prompt window from the Visual Studio installation directory and compile the `cmdll.c` file by typing **cl -LD cmdll.c** at the command prompt. +1. Open a Visual Studio x64 (or x86) Native Tools Command Prompt window from the Visual Studio installation directory and compile the `cmdll.c` file by typing **cl -LD cmdll.c** at the command prompt. -3. In the same directory, create the following C# file and name it `cm.cs`: +1. In the same directory, create the following C# file and name it `cm.cs`: ```csharp // cm.cs @@ -66,15 +63,15 @@ This example illustrates a C# program that calls into a C library (a native DLL) } ``` -4. Open a Visual Studio x64 (or x32) Native Tools Command Prompt window from the Visual Studio installation directory and compile the `cm.cs` file by typing: +1. Open a Visual Studio x64 (or x86) Native Tools Command Prompt window from the Visual Studio installation directory and compile the `cm.cs` file by typing: > **csc cm.cs** (for the x64 command prompt) > —or— - > **csc -platform:x86 cm.cs** (for the x32 command prompt) + > **csc -platform:x86 cm.cs** (for the x86 command prompt) - This will create the executable file `cm.exe`. + This command creates the executable file `cm.exe`. -5. Run `cm.exe`. The `SampleMethod` method passes the value 5 to the DLL file, which returns the value multiplied by 10. The program produces the following output: +1. Run `cm.exe`. The `SampleMethod` method passes the value 5 to the DLL file, which returns the value multiplied by 10. The program produces the following output: ```output SampleMethod() returns 50. diff --git a/docs/csharp/language-reference/keywords/field.md b/docs/csharp/language-reference/keywords/field.md index 39c6f6accefde..087a054d3237e 100644 --- a/docs/csharp/language-reference/keywords/field.md +++ b/docs/csharp/language-reference/keywords/field.md @@ -1,7 +1,7 @@ --- description: "The `field` contextual keyword - access the compiler synthesized backing field for a property" title: "The `field` contextual keyword" -ms.date: 11/18/2025 +ms.date: 01/21/2026 f1_keywords: - "field_CSharpKeyword" helpviewer_keywords: @@ -9,13 +9,15 @@ helpviewer_keywords: --- # `field` - Field backed property declarations -The contextual keyword `field`, added in C# 14, can be used in a property accessor to access the compiler synthesized backing field of a property. This syntax enables you to define the body of a `get` or `set` accessor and let the compiler generate the other accessor as it would in an automatically implemented property. +Use the contextual keyword `field`, introduced in C# 14, in a property accessor to access the compiler-synthesized backing field of a property. By using this syntax, you can define the body of a `get` or `set` accessor and let the compiler generate the other accessor as it would in an automatically implemented property. -The addition of the `field` contextual keywords provides a smooth path to add benefits such as range checking to an automatically implemented property. This practice is shown in the following example: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +The addition of the `field` contextual keyword provides a smooth path to add benefits such as range checking to an automatically implemented property. This practice is shown in the following example: :::code language="csharp" source="./snippets/PropertyAccessors.cs" id="FieldBackedProperty"::: -You might implement the `Hours` property as an automatically implemented property. Then, you discover that you want to protect against a negative value. You use `field` and provide range checking in the `set` accessor. You don't need to declare the backing field by hand and provide a body for the `get` accessor. +You might implement the `Hours` property as an automatically implemented property. Then, you discover that you want to protect against a negative value. Use `field` and provide range checking in the `set` accessor. You don't need to declare the backing field by hand or provide a body for the `get` accessor. For more information, see the [Properties](../../programming-guide/classes-and-structs/properties.md) and [Indexers](../../programming-guide/indexers/index.md) articles. diff --git a/docs/csharp/language-reference/keywords/file.md b/docs/csharp/language-reference/keywords/file.md index 702b3248d3877..358c2a9389626 100644 --- a/docs/csharp/language-reference/keywords/file.md +++ b/docs/csharp/language-reference/keywords/file.md @@ -1,7 +1,7 @@ --- description: "The file modifier: Declare types whose visibility is the containing file" title: "The file keyword" -ms.date: 11/18/2025 +ms.date: 01/21/2026 f1_keywords: - "file_CSharpKeyword" helpviewer_keywords: @@ -9,7 +9,11 @@ helpviewer_keywords: --- # The file modifier -The `file` modifier restricts a top-level type's visibility to the file containing its declaration. The `file` modifier is most often applied to types written by a source generator. File-local types provide source generators with a convenient way to avoid name collisions among generated types. The `file` modifier declares a file-local type, as in this example: +The `file` modifier restricts a top-level type's visibility to the file containing its declaration. Source generators most often apply the `file` modifier to types they generate. File-local types provide source generators with a convenient way to avoid name collisions among generated types. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +The `file` modifier declares a file-local type, as in this example: ```csharp file class HiddenWidget @@ -20,7 +24,7 @@ file class HiddenWidget Any types nested within a file-local type are also only visible within the file containing its declaration. Other types in an assembly can use the same name as a file-local type. Because the file-local type is visible only in the file containing its declaration, these types don't create a naming collision. -A file-local type can't be the return type or parameter type of any member declared in a non-file-local type. A file-local type can't be a field member of a non-file-local. However, a more visible type can implicitly implement a file-local interface type. The type can also [explicitly implement](../../programming-guide/interfaces/explicit-interface-implementation.md) a file-local interface but explicit implementations can only be used within the same file. +A file-local type can't be the return type or parameter type of any member declared in a non-file-local type. A file-local type can't be a field member of a non-file-local type. However, a more visible type can implicitly implement a file-local interface type. The type can also [explicitly implement](../../programming-guide/interfaces/explicit-interface-implementation.md) a file-local interface but explicit implementations can only be used within the same file. The following example shows a public type that uses a file-local type to provide a worker method. In addition, the public type implements a file-local interface implicitly: diff --git a/docs/csharp/language-reference/keywords/from-clause.md b/docs/csharp/language-reference/keywords/from-clause.md index c65aeb5c7480e..97fba0136d8ff 100644 --- a/docs/csharp/language-reference/keywords/from-clause.md +++ b/docs/csharp/language-reference/keywords/from-clause.md @@ -1,50 +1,50 @@ --- description: "from clause - C# Reference" title: "from clause" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "from_CSharpKeyword" - "from" helpviewer_keywords: - "from clause [C#]" - "from keyword [C#]" -ms.assetid: 1aefd18c-1314-47f8-99ec-9bcefb09e699 --- # from clause (C# Reference) -A query expression must begin with a `from` clause. Additionally, a query expression can contain sub-queries, which also begin with a `from` clause. The `from` clause specifies the following: - -- The data source on which the query or sub-query will be run. +A query expression must begin with a `from` clause. Additionally, a query expression can contain subqueries, which also begin with a `from` clause. The `from` clause specifies the following: +- The data source on which the query or subquery runs. - A local *range variable* that represents each element in the source sequence. Both the range variable and the data source are strongly typed. The data source referenced in the `from` clause must have a type of , , or a derived type such as . +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + In the following example, `numbers` is the data source and `num` is the range variable. Note that both variables are strongly typed even though the [var](../statements//declarations.md#implicitly-typed-local-variables) keyword is used. -[!code-csharp[cscsrefQueryKeywords#1](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/From.cs#1)] +:::code language="csharp" source="./snippets/from.cs" id="1"::: ## The range variable -The compiler infers the type of the range variable when the data source implements . For example, if the source has a type of `IEnumerable`, then the range variable is inferred to be `Customer`. The only time that you must specify the type explicitly is when the source is a non-generic `IEnumerable` type such as . For more information, see [How to query an ArrayList with LINQ](../../linq/how-to-query-collections.md). +The compiler infers the type of the range variable when the data source implements . For example, if the source has a type of `IEnumerable`, then the range variable is inferred to be `Customer`. You must specify the type explicitly only when the source is a non-generic `IEnumerable` type such as . For more information, see [How to query an ArrayList with LINQ](../../linq/how-to-query-collections.md). -In the previous example `num` is inferred to be of type `int`. Because the range variable is strongly typed, you can call methods on it or use it in other operations. For example, instead of writing `select num`, you could write `select num.ToString()` to cause the query expression to return a sequence of strings instead of integers. Or you could write `select num + 10` to cause the expression to return the sequence 14, 11, 13, 12, 10. For more information, see [select clause](select-clause.md). +In the previous example, `num` is inferred to be of type `int`. Because the range variable is strongly typed, you can call methods on it or use it in other operations. For example, instead of writing `select num`, you could write `select num.ToString()` to cause the query expression to return a sequence of strings instead of integers. Or you could write `select num + 10` to cause the expression to return the sequence 14, 11, 13, 12, 10. For more information, see [select clause](select-clause.md). -The range variable is like an iteration variable in a [foreach](../statements/iteration-statements.md#the-foreach-statement) statement except for one very important difference: a range variable never actually stores data from the source. It's just a syntactic convenience that enables the query to describe what will occur when the query is executed. For more information, see [Introduction to LINQ Queries (C#)](../../linq/get-started/introduction-to-linq-queries.md). +The range variable is like an iteration variable in a [foreach](../statements/iteration-statements.md#the-foreach-statement) statement except for one very important difference: a range variable never actually stores data from the source. It's just a syntactic convenience that enables the query to describe what occurs when the query is executed. For more information, see [Introduction to LINQ Queries (C#)](../../linq/get-started/introduction-to-linq-queries.md). ## Compound from clauses -In some cases, each element in the source sequence may itself be either a sequence or contain a sequence. For example, your data source may be an `IEnumerable` where each student object in the sequence contains a list of test scores. To access the inner list within each `Student` element, you can use compound `from` clauses. The technique is like using nested [foreach](../statements/iteration-statements.md#the-foreach-statement) statements. You can add [where](partial-member.md) or [orderby](orderby-clause.md) clauses to either `from` clause to filter the results. The following example shows a sequence of `Student` objects, each of which contains an inner `List` of integers representing test scores. To access the inner list, use a compound `from` clause. You can insert clauses between the two `from` clauses if necessary. +In some cases, each element in the source sequence might itself be either a sequence or contain a sequence. For example, your data source might be an `IEnumerable` where each student object in the sequence contains a list of test scores. To access the inner list within each `Student` element, you can use compound `from` clauses. The technique is like using nested [foreach](../statements/iteration-statements.md#the-foreach-statement) statements. You can add [where](partial-member.md) or [orderby](orderby-clause.md) clauses to either `from` clause to filter the results. The following example shows a sequence of `Student` objects, each of which contains an inner `List` of integers representing test scores. To access the inner list, use a compound `from` clause. You can insert clauses between the two `from` clauses if necessary. -[!code-csharp[cscsrefQueryKeywords#2](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/From.cs#2)] +:::code language="csharp" source="./snippets/from.cs" id="2"::: -## Using Multiple from Clauses to Perform Joins +## Using multiple from clauses to perform joins -A compound `from` clause is used to access inner collections in a single data source. However, a query can also contain multiple `from` clauses that generate supplemental queries from independent data sources. This technique enables you to perform certain types of join operations that are not possible by using the [join clause](join-clause.md). +Use a compound `from` clause to access inner collections in a single data source. However, a query can also contain multiple `from` clauses that generate supplemental queries from independent data sources. By using this technique, you can perform certain types of join operations that aren't possible by using the [join clause](join-clause.md). -The following example shows how two `from` clauses can be used to form a complete cross join of two data sources. +The following example shows how two `from` clauses form a complete cross join of two data sources. -[!code-csharp[cscsrefQueryKeywords#3](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/From.cs#3)] +:::code language="csharp" source="./snippets/from.cs" id="3"::: For more information about join operations that use multiple `from` clauses, see [Perform left outer joins](../../linq/standard-query-operators/join-operations.md). diff --git a/docs/csharp/language-reference/keywords/get.md b/docs/csharp/language-reference/keywords/get.md index 159f7ac1344c3..0703b2dde85af 100644 --- a/docs/csharp/language-reference/keywords/get.md +++ b/docs/csharp/language-reference/keywords/get.md @@ -1,7 +1,7 @@ --- description: "The C# get keyword declares a get accessor in a property or indexer. It defines the code to retrieve the value of the property or indexed property." title: "The get keyword: property accessor" -ms.date: 11/18/2025 +ms.date: 01/21/2026 f1_keywords: - "get_CSharpKeyword" - "get" @@ -12,18 +12,20 @@ helpviewer_keywords: The `get` keyword defines an *accessor* method in a property or indexer that returns the property value or the indexer element. For more information, see [Properties](../../programming-guide/classes-and-structs/properties.md), [Automatically implemented Properties](../../programming-guide/classes-and-structs/auto-implemented-properties.md), and [Indexers](../../programming-guide/indexers/index.md). -For simple cases in which a property's `get` and `set` accessors perform no other operation than setting or retrieving a value in a private backing field, you can take advantage of the C# compiler's support for automatically implemented properties. The following example implements `Hours` as an automatically implemented property. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +For simple cases where a property's `get` and `set` accessors perform no other operation than setting or retrieving a value in a private backing field, take advantage of the C# compiler's support for automatically implemented properties. The following example implements `Hours` as an automatically implemented property. :::code language="csharp" source="./snippets/PropertyAccessors.cs" id="AutoImplementedProperties"::: > [!IMPORTANT] -> Automatically implemented properties aren't allowed for [interface property declarations](../../programming-guide/classes-and-structs/interface-properties.md) or the implementing declaration for a [partial property](./partial-member.md). The compiler interprets syntax matching an automatically implemented property as the declaring declaration, not an implementing declaration. +> You can't use automatically implemented properties for [interface property declarations](../../programming-guide/classes-and-structs/interface-properties.md) or the implementing declaration for a [partial property](./partial-member.md). The compiler interprets syntax matching an automatically implemented property as the declaring declaration, not an implementing declaration. Often, the `get` accessor consists of a single statement that returns a value, as it did in the previous example. You can implement the `get` accessor as an expression-bodied member. The following example implements both the `get` and the `set` accessor as expression-bodied members. :::code language="csharp" source="./snippets/PropertyAccessors.cs" id="GetSetExpressions"::: -You might find that you need to implement one of the accessor bodies. You can use a field backed property to let the compiler generate one accessor while you write the other by hand. You use the `field` keyword, added in C# 14, to access the compiler synthesized backing field: +You might find that you need to implement one of the accessor bodies. Use a field backed property to let the compiler generate one accessor while you write the other by hand. Use the `field` keyword, added in C# 14, to access the compiler synthesized backing field: :::code language="csharp" source="./snippets/PropertyAccessors.cs" id="FieldBackedProperty"::: diff --git a/docs/csharp/language-reference/keywords/group-clause.md b/docs/csharp/language-reference/keywords/group-clause.md index 7bdaee3f3d25c..958d4da224acb 100644 --- a/docs/csharp/language-reference/keywords/group-clause.md +++ b/docs/csharp/language-reference/keywords/group-clause.md @@ -1,34 +1,35 @@ --- description: "group clause - C# Reference" title: "group clause" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "group" - "group_CSharpKeyword" helpviewer_keywords: - "group keyword [C#]" - "group clause [C#]" -ms.assetid: c817242e-b12c-4baa-a57e-73ee138f34d1 --- # group clause (C# Reference) -The `group` clause returns a sequence of objects that contain zero or more items that match the key value for the group. For example, you can group a sequence of strings according to the first letter in each string. In this case, the first letter is the key and has a type [char](../builtin-types/char.md), and is stored in the `Key` property of each object. The compiler infers the type of the key. +The `group` clause returns a sequence of objects. The sequence contains zero or more items that match the key value for the group. For example, you can group a sequence of strings according to the first letter in each string. In this case, the first letter is the key and has a type [char](../builtin-types/char.md). Each object stores this key in its `Key` property. The compiler infers the type of the key. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] You can end a query expression with a `group` clause, as shown in the following example: -[!code-csharp[cscsrefQueryKeywords#10](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs#10)] +:::code language="csharp" source="./snippets/group.cs" id="10"::: -If you want to perform additional query operations on each group, you can specify a temporary identifier by using the [into](into.md) contextual keyword. When you use `into`, you must continue with the query, and eventually end it with either a `select` statement or another `group` clause, as shown in the following excerpt: +If you want to perform additional query operations on each group, specify a temporary identifier by using the [into](into.md) contextual keyword. When you use `into`, you must continue with the query, and eventually end it with either a `select` statement or another `group` clause, as shown in the following excerpt: -[!code-csharp[cscsrefQueryKeywords#11](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs#11)] +:::code language="csharp" source="./snippets/group.cs" id="11"::: More complete examples of the use of `group` with and without `into` are provided in the Example section of this article. ## Enumerating the results of a group query -Because the objects produced by a `group` query are essentially a list of lists, you must use a nested [foreach](../statements/iteration-statements.md#the-foreach-statement) loop to access the items in each group. The outer loop iterates over the group keys, and the inner loop iterates over each item in the group itself. A group may have a key but no elements. The following is the `foreach` loop that executes the query in the previous code examples: +Because the objects that a `group` query produces are essentially a list of lists, you must use a nested [foreach](../statements/iteration-statements.md#the-foreach-statement) loop to access the items in each group. The outer loop iterates over the group keys, and the inner loop iterates over each item in the group itself. A group can have a key but no elements. The following `foreach` loop executes the query in the previous code examples: -[!code-csharp[cscsrefQueryKeywords#12](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs#12)] +:::code language="csharp" source="./snippets/group.cs" id="12"::: ## Key types @@ -36,51 +37,47 @@ Group keys can be any type, such as a string, a built-in numeric type, or a user ### Grouping by string -The previous code examples used a `char`. A string key could easily have been specified instead, for example the complete last name: +The previous code examples used a `char`. You can also specify a string key, such as the complete last name: -[!code-csharp[cscsrefQueryKeywords#13](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs#13)] +:::code language="csharp" source="./snippets/group.cs" id="13"::: ### Grouping by bool -The following example shows the use of a bool value for a key to divide the results into two groups. Note that the value is produced by a sub-expression in the `group` clause. +The following example uses a bool value for a key to divide the results into two groups. The value comes from a sub-expression in the `group` clause. -[!code-csharp[cscsrefQueryKeywords#14](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs#14)] +:::code language="csharp" source="./snippets/group.cs" id="14"::: ### Grouping by numeric range -The next example uses an expression to create numeric group keys that represent a percentile range. Note the use of [let](let-clause.md) as a convenient location to store a method call result, so that you don't have to call the method two times in the `group` clause. For more information about how to safely use methods in query expressions, see [Handle exceptions in query expressions](../../linq/get-started/write-linq-queries.md). +The next example uses an expression to create numeric group keys that represent a percentile range. It uses [`let`](let-clause.md) to store a method call result, so you don't have to call the method twice in the `group` clause. For more information about how to safely use methods in query expressions, see [Handle exceptions in query expressions](../../linq/get-started/write-linq-queries.md). -[!code-csharp[cscsrefQueryKeywords#15](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs#15)] +:::code language="csharp" source="./snippets/group.cs" id="15"::: ### Grouping by composite keys -Use a composite key when you want to group elements according to more than one key. You create a composite key by using an anonymous type or a named type to hold the key element. In the following example, assume that a class `Person` has been declared with members named `surname` and `city`. The `group` clause causes a separate group to be created for each set of persons with the same last name and the same city. +Use a composite key when you want to group elements by more than one key. Create a composite key by using an anonymous type or a named type to hold the key element. In the following example, assume that a class `Person` has members named `surname` and `city`. The `group` clause creates a separate group for each set of persons with the same last name and the same city. ```csharp group person by new {name = person.surname, city = person.city}; ``` -Use a named type if you must pass the query variable to another method. Create a special class using automatically implemented properties for the keys, and then override the and methods. You can also use a struct, in which case you do not strictly have to override those methods. For more information see [How to implement a lightweight class with automatically implemented properties](../../programming-guide/classes-and-structs/how-to-implement-a-lightweight-class-with-auto-implemented-properties.md) and [How to query for duplicate files in a directory tree](../../linq/how-to-query-files-and-directories.md). The latter article has a code example that demonstrates how to use a composite key with a named type. - -## Example 1 - -The following example shows the standard pattern for ordering source data into groups when no additional query logic is applied to the groups. This is called a grouping without a continuation. The elements in an array of strings are grouped according to their first letter. The result of the query is an type that contains a public `Key` property of type `char` and an collection that contains each item in the grouping. +Use a named type if you need to pass the query variable to another method. Create a special class with automatically implemented properties for the keys, and then override the and methods. You can also use a struct, which doesn't strictly require those method overrides. For more information, see [How to implement a lightweight class with automatically implemented properties](../../programming-guide/classes-and-structs/how-to-implement-a-lightweight-class-with-auto-implemented-properties.md) and [How to query for duplicate files in a directory tree](../../linq/how-to-query-files-and-directories.md). The latter article has a code example that demonstrates how to use a composite key with a named type. -The result of a `group` clause is a sequence of sequences. Therefore, to access the individual elements within each returned group, use a nested `foreach` loop inside the loop that iterates the group keys, as shown in the following example. +## Examples -[!code-csharp[cscsrefQueryKeywords#16](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs#16)] +The following example shows the standard pattern for ordering source data into groups when you don't apply any extra query logic to the groups. This pattern is called grouping without a continuation. The example groups the elements in an array of strings according to their first letter. The result of the query is an type that contains a public `Key` property of type `char` and an collection that contains each item in the grouping. -## Example 2 +The result of a `group` clause is a sequence of sequences. To access the individual elements within each returned group, use a nested `foreach` loop inside the loop that iterates the group keys, as shown in the following example. -This example shows how to perform additional logic on the groups after you have created them, by using a *continuation* with `into`. For more information, see [into](into.md). The following example queries each group to select only those whose key value is a vowel. +:::code language="csharp" source="./snippets/group.cs" id="16"::: -[!code-csharp[cscsrefQueryKeywords#17](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs#17)] +The following example shows how to perform extra logic on the groups after you create them, by using a *continuation* with `into`. For more information, see [`into`](into.md). The following example queries each group to select only those whose key value is a vowel. -## Remarks +:::code language="csharp" source="./snippets/group.cs" id="17"::: -At compile time, `group` clauses are translated into calls to the method. +At compile time, the compiler translates `group` clauses into calls to the method. -Custom equality comparer is not supported in the syntax of `group` clause query. Use method explicitly if you want to utilize in your query. +The syntax of `group` clause query doesn't support custom equality comparer. If you want to use in your query, explicitly use the method. ## See also diff --git a/docs/csharp/language-reference/keywords/in-generic-modifier.md b/docs/csharp/language-reference/keywords/in-generic-modifier.md index 656c395785123..8f2f35ee69d73 100644 --- a/docs/csharp/language-reference/keywords/in-generic-modifier.md +++ b/docs/csharp/language-reference/keywords/in-generic-modifier.md @@ -1,22 +1,24 @@ --- description: "in (Generic Modifier) - C# Reference" title: "in (Generic Modifier)" -ms.date: 07/20/2015 +ms.date: 01/21/2026 helpviewer_keywords: - "contravariance, in keyword [C#]" - "in keyword [C#]" --- -# in (Generic Modifier) (C# Reference) +# `in` (Generic Modifier) (C# Reference) -For generic type parameters, the `in` keyword specifies that the type parameter is contravariant. You can use the `in` keyword in generic interfaces and delegates. +For generic type parameters, use the `in` keyword to allow contravariant type arguments. Use the `in` keyword in generic interfaces and delegates. -Contravariance enables you to use a less derived type than that specified by the generic parameter. This allows for implicit conversion of classes that implement contravariant interfaces and implicit conversion of delegate types. Covariance and contravariance in generic type parameters are supported for reference types, but they are not supported for value types. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -A type can be declared contravariant in a generic interface or delegate only if it defines the type of a method's parameters and not of a method's return type. `In`, `ref`, and `out` parameters must be invariant, meaning they are neither covariant nor contravariant. +Contravariance enables you to use a less derived type than the type specified by the generic parameter. This feature allows for implicit conversion of classes that implement contravariant interfaces and implicit conversion of delegate types. Reference types support covariance and contravariance in generic type parameters, but value types don't support these features. -An interface that has a contravariant type parameter allows its methods to accept arguments of less derived types than those specified by the interface type parameter. For example, in the interface, type T is contravariant, you can assign an object of the `IComparer` type to an object of the `IComparer` type without using any special conversion methods if `Employee` inherits `Person`. +You can declare a type as contravariant in a generic interface or delegate only if it defines the type of a method's parameters and not the method's return type. `In`, `ref`, and `out` parameters must be invariant, meaning they're neither covariant nor contravariant. -A contravariant delegate can be assigned another delegate of the same type, but with a less derived generic type parameter. +An interface that has a contravariant type parameter allows its methods to accept arguments of less derived types than those specified by the interface type parameter. For example, in the interface, type T is contravariant. You can assign an object of the `IComparer` type to an object of the `IComparer` type without using any special conversion methods if `Employee` inherits `Person`. + +You can assign a contravariant delegate to another delegate of the same type, but with a less derived generic type parameter. For more information, see [Covariance and Contravariance](../../programming-guide/concepts/covariance-contravariance/index.md). @@ -24,13 +26,13 @@ For more information, see [Covariance and Contravariance](../../programming-guid The following example shows how to declare, extend, and implement a contravariant generic interface. It also shows how you can use implicit conversion for classes that implement this interface. -[!code-csharp[csVarianceKeywords#1](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csvariancekeywords/cs/program.cs#1)] +:::code language="csharp" source="./snippets/variance.cs" id="1"::: ## Contravariant generic delegate The following example shows how to declare, instantiate, and invoke a contravariant generic delegate. It also shows how you can implicitly convert a delegate type. -[!code-csharp[csVarianceKeywords#2](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csvariancekeywords/cs/program.cs#2)] +:::code language="csharp" source="./snippets/variance.cs" id="2"::: ## C# language specification diff --git a/docs/csharp/language-reference/keywords/in.md b/docs/csharp/language-reference/keywords/in.md index 88c72975dbefb..f2c7874af3dbc 100644 --- a/docs/csharp/language-reference/keywords/in.md +++ b/docs/csharp/language-reference/keywords/in.md @@ -1,7 +1,7 @@ --- description: "in - C# Reference" title: "in keyword" -ms.date: 02/06/2018 +ms.date: 01/21/2026 f1_keywords: - "in" - "in_CSharpKeyword" @@ -9,16 +9,16 @@ helpviewer_keywords: - "in keyword [C#]" --- -# in (C# Reference) +# `in` (C# reference) -The `in` keyword is used in the following contexts: +Use the `in` keyword in the following contexts: -- [generic type parameters](in-generic-modifier.md) in generic interfaces and delegates. -- As a [parameter modifier](method-parameters.md#in-parameter-modifier), which lets you pass an argument to a method by reference rather than by value. +- [Generic type parameters](in-generic-modifier.md) in generic interfaces and delegates. +- As a [parameter modifier](method-parameters.md#in-parameter-modifier), which you use to pass an argument to a method by reference rather than by value. - [foreach](../statements/iteration-statements.md#the-foreach-statement) statements. - [from clauses](from-clause.md) in LINQ query expressions. - [join clauses](join-clause.md) in LINQ query expressions. - + ## See also - [C# Keywords](index.md) diff --git a/docs/csharp/language-reference/keywords/index.md b/docs/csharp/language-reference/keywords/index.md index 8fd3b1292cac4..41542291e91ac 100644 --- a/docs/csharp/language-reference/keywords/index.md +++ b/docs/csharp/language-reference/keywords/index.md @@ -1,7 +1,7 @@ --- description: "C# Keywords: Find the reference material for the predefined keywords and contextual keywords defined in the C# language." title: "C# Keywords and contextual keywords" -ms.date: 04/17/2025 +ms.date: 01/21/2026 f1_keywords: - "cs.keywords" helpviewer_keywords: @@ -11,11 +11,13 @@ helpviewer_keywords: - "@ keyword" ms.custom: "updateeachrelease" --- -# C# Keywords +# C# keywords -Keywords are predefined, reserved identifiers that have special meanings to the compiler. They can't be used as identifiers in your program unless they include `@` as a prefix. For example, `@if` is a valid identifier, but `if` isn't because `if` is a keyword. +Keywords are predefined, reserved identifiers that have special meanings to the compiler. You can't use them as identifiers in your program unless you prefix them with `@`. For example, `@if` is a valid identifier, but `if` isn't because `if` is a keyword. -The first table in this article lists keywords that are reserved identifiers in any part of a C# program. The second table in this article lists the contextual keywords in C#. Contextual keywords have special meaning only in a limited program context and can be used as identifiers outside that context. Generally, as new keywords are added to the C# language, they're added as contextual keywords in order to avoid breaking programs written in earlier versions. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +The first table in this article lists keywords that are reserved identifiers in any part of a C# program. The second table lists the contextual keywords in C#. Contextual keywords have special meaning only in a limited program context and can be used as identifiers outside that context. Generally, as new keywords are added to the C# language, they're added as contextual keywords to avoid breaking programs written in earlier versions. :::row::: :::column::: @@ -107,7 +109,7 @@ The first table in this article lists keywords that are reserved identifiers in ## Contextual keywords -A contextual keyword is used to provide a specific meaning in the code, but it isn't a reserved word in C#. Some contextual keywords, such as `partial` and `where`, have special meanings in two or more contexts. +A contextual keyword provides a specific meaning in the code, but it isn't a reserved word in C#. Some contextual keywords, such as `partial` and `where`, have special meanings in two or more contexts. :::row::: :::column::: diff --git a/docs/csharp/language-reference/keywords/init.md b/docs/csharp/language-reference/keywords/init.md index 13b3f5a9b8676..8a89b758f40a9 100644 --- a/docs/csharp/language-reference/keywords/init.md +++ b/docs/csharp/language-reference/keywords/init.md @@ -1,7 +1,7 @@ --- description: "The `init` keyword is used to declare a `set` accessor that can only be called during an object's initialization: either by a constructor or as part of an object initializer." title: "The init keyword - init only properties" -ms.date: 11/18/2025 +ms.date: 01/21/2026 f1_keywords: - "init" - "init_CSharpKeyword" @@ -10,14 +10,16 @@ helpviewer_keywords: --- # The `init` keyword (C# Reference) -The `init` keyword defines an *accessor* method in a property or indexer. An init-only setter assigns a value to the property or the indexer element **only** during object construction. An `init` enforces immutability, so that once the object is initialized, it can't be changed. An `init` accessor enables calling code to use an [object initializer](../../programming-guide/classes-and-structs/how-to-initialize-objects-by-using-an-object-initializer.md) to set the initial value. As a contrast, an - [automatically implemented property](../../programming-guide/classes-and-structs/auto-implemented-properties.md) with only a `get` setter must be initialized by calling a constructor. A property with a `private set` accessor can be modified after construction, but only in the class. +The `init` keyword defines an *accessor* method in a property or indexer. An init-only setter assigns a value to the property or the indexer element **only** during object construction. An `init` enforces immutability, so that once the object is initialized, it can't be changed. An `init` accessor enables calling code to use an [object initializer](../../programming-guide/classes-and-structs/how-to-initialize-objects-by-using-an-object-initializer.md) to set the initial value. In contrast, an + [automatically implemented property](../../programming-guide/classes-and-structs/auto-implemented-properties.md) with only a `get` accessor must be initialized by calling a constructor. A property with a `private set` accessor can be modified after construction, but only in the class. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] The following code demonstrates an `init` accessor in an automatically implemented property: :::code language="csharp" source="snippets/InitExample2.cs"::: -You might need to implement one of the accessors to provide parameter validation. You can do that using the `field` keyword, introduced in C# 14. The `field` keyword accesses the compiler synthesized backing field for that property. The following example shows a property where the `init` accessor validates the range of the `value` parameter." +You might need to implement one of the accessors to provide parameter validation. You can do that validation by using the `field` keyword, introduced in C# 14. The `field` keyword accesses the compiler synthesized backing field for that property. The following example shows a property where the `init` accessor validates the range of the `value` parameter. :::code language="csharp" source="snippets/InitExample5.cs"::: @@ -33,11 +35,11 @@ An `init` accessor doesn't force callers to set the property. Instead, it allows :::code language="csharp" source="./snippets/InitNullablityExample.cs" id="Snippet4"::: -To force callers to set an initial non-null value, you add the `required` modifier, as shown in the following example: +To force callers to set an initial non-null value, add the `required` modifier, as shown in the following example: :::code language="csharp" source="./snippets/InitNullablityExample.cs" id="SnippetNonNullable"::: -The following example shows the distinction between a `private set`, read only, and `init` property. Both the private set version and the read only version require callers to use the added constructor to set the name property. The `private set` version allows a person to change their name after the instance is constructed. The `init` version doesn't require a constructor. Callers can initialize the properties using an object initializer: +The following example shows the distinction between a `private set`, read-only, and `init` property. Both the private set version and the read-only version require callers to use the added constructor to set the name property. The `private set` version allows a person to change their name after the instance is constructed. The `init` version doesn't require a constructor. Callers can initialize the properties by using an object initializer: :::code language="csharp" source="snippets/InitExample4.cs" id="SnippetClassDefinitions"::: diff --git a/docs/csharp/language-reference/keywords/interface.md b/docs/csharp/language-reference/keywords/interface.md index 71f727451c986..1ed5f5784bce8 100644 --- a/docs/csharp/language-reference/keywords/interface.md +++ b/docs/csharp/language-reference/keywords/interface.md @@ -1,7 +1,7 @@ --- description: "Use the `interface` keyword to define contracts that any implementing type must support. Interfaces provide the means to create common behavior among a set of unrelated types." title: "interface keyword" -ms.date: 11/18/2024 +ms.date: 01/21/2026 f1_keywords: - "interface_CSharpKeyword" helpviewer_keywords: @@ -15,17 +15,19 @@ An interface can define a [default implementation](#default-interface-members) f An interface can define `static abstract` or `static virtual` members to declare that an implementing type must provide the declared members. Typically, `static virtual` methods declare that an implementation must define a set of [overloaded operators](../operators/operator-overloading.md). +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + In the following example, class `ImplementationClass` must implement a method named `SampleMethod` that has no parameters and returns `void`. -[!code-csharp[csrefKeywordsTypes#14](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsTypes/CS/keywordsTypes.cs#14)] +:::code language="csharp" source="./snippets/keywordsTypes.cs" id="14"::: For more information and examples, see [Interfaces](../../fundamentals/types/interfaces.md). ## Access modifiers -An interface can be a member of a namespace or a class. A top-level interface, one declared in a namespace but not nested inside another type, can be declared `public` or `internal`. The default is `internal`. Nested interface declarations, declared inside another type, can be declared using any access modifier. +An interface can be a member of a namespace or a class. You can declare a top-level interface, one declared in a namespace but not nested inside another type, as `public` or `internal`. The default is `internal`. You can declare nested interface declarations, declared inside another type, by using any access modifier. -Interface members *without* an implementation (abstract members) are implicitly `public` and can't have any other access modifier. Interface members *with* a default implementation are `private` by default if no access modifier is specified, but can be declared with any access modifier (`public`, `private`, `protected`, or `internal`). +Interface members *without* an implementation (abstract members) are implicitly `public` and can't have any other access modifier. Interface members *with* a default implementation are `private` by default if you don't specify an access modifier, but you can declare any access modifier (`public`, `private`, `protected`, or `internal`). ## Interface members @@ -44,17 +46,17 @@ An interface declaration can contain the following members: ## Default interface members -Member declarations typically don't contain a body, however, an interface member can declare a body. Member bodies in an interface are the *default implementation*. Members with bodies permit the interface to provide a "default" implementation for classes and structs that don't provide an overriding implementation. +Member declarations typically don't contain a body. However, an interface member can declare a body. Member bodies in an interface are the *default implementation*. By using members with bodies, the interface can provide a default implementation for classes and structs that don't provide an overriding implementation. > [!IMPORTANT] -> Adding default interfaces members forces any `ref struct` that implements the interface to add an explicit declaration of that member. +> If you add default interfaces members, any `ref struct` that implements the interface must explicitly declare that member. ## Static abstract and virtual members -An interface can declare `static abstract` and `static virtual` members for all member types except fields. Interfaces can declare that implementing types must define operators or other static members. This feature enables generic algorithms to specify number-like behavior. You can see examples in the numeric types in the .NET runtime, such as . These interfaces define common mathematical operators implemented by many numeric types. The compiler must resolve calls to `static virtual` and `static abstract` methods at compile time. The `static virtual` and `static abstract` methods declared in interfaces don't have a runtime dispatch mechanism analogous to `virtual` or `abstract` methods declared in classes. Instead, the compiler uses type information available at compile time. Therefore, `static virtual` methods are almost exclusively declared in [generic interfaces](../../programming-guide/generics/generic-interfaces.md). Furthermore, most interfaces that declare `static virtual` or `static abstract` methods declare that one of the type parameters must [implement the declared interface](../../programming-guide/generics/constraints-on-type-parameters.md#type-arguments-implement-declared-interface). For example, the `INumber` interface declares that `T` must implement `INumber`. The compiler uses the type argument to resolve calls to the methods and operators declared in the interface declaration. For example, the `int` type implements `INumber`. When the type parameter `T` denotes the type argument `int`, the `static` members declared on `int` are invoked. Alternatively, when `double` is the type argument, the `static` members declared on the `double` type are invoked. +An interface can declare `static abstract` and `static virtual` members for all member types except fields. By declaring these members, an interface can require that implementing types define operators or other static members. This feature enables generic algorithms to specify number-like behavior. You can see examples in the numeric types in the .NET runtime, such as . These interfaces define common mathematical operators implemented by many numeric types. The compiler must resolve calls to `static virtual` and `static abstract` methods at compile time. The `static virtual` and `static abstract` methods declared in interfaces don't have a runtime dispatch mechanism analogous to `virtual` or `abstract` methods declared in classes. Instead, the compiler uses type information available at compile time. Therefore, `static virtual` methods are almost exclusively declared in [generic interfaces](../../programming-guide/generics/generic-interfaces.md). Furthermore, most interfaces that declare `static virtual` or `static abstract` methods declare that one of the type parameters must [implement the declared interface](../../programming-guide/generics/constraints-on-type-parameters.md#type-arguments-implement-declared-interface). For example, the `INumber` interface declares that `T` must implement `INumber`. The compiler uses the type argument to resolve calls to the methods and operators declared in the interface declaration. For example, the `int` type implements `INumber`. When the type parameter `T` denotes the type argument `int`, the `static` members declared on `int` are invoked. Alternatively, when `double` is the type argument, the `static` members declared on the `double` type are invoked. > [!IMPORTANT] -> Method dispatch for `static abstract` and `static virtual` methods declared in interfaces is resolved using the compile time type of an expression. If the runtime type of an expression is derived from a different compile time type, the static methods on the base (compile time) type are called. +> Method dispatch for `static abstract` and `static virtual` methods declared in interfaces is resolved by using the compile-time type of an expression. If the runtime type of an expression is derived from a different compile-time type, the static methods on the base (compile-time) type are called. You can try this feature by working with the tutorial on [static abstract members in interfaces](../../advanced-topics/interface-implementation/static-virtual-interface-members.md). diff --git a/docs/csharp/language-reference/keywords/internal.md b/docs/csharp/language-reference/keywords/internal.md index ca41f289cfcc3..db52086d1d91d 100644 --- a/docs/csharp/language-reference/keywords/internal.md +++ b/docs/csharp/language-reference/keywords/internal.md @@ -1,95 +1,95 @@ --- description: "internal - C# Reference" title: "internal keyword" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "internal_CSharpKeyword" - "internal" helpviewer_keywords: - "internal keyword [C#]" -ms.assetid: 6ee0785c-d7c8-49b8-bb72-0a4dfbcb6461 --- -# internal (C# Reference) +# internal (C# reference) The `internal` keyword is an [access modifier](./access-modifiers.md) for types and type members. - - > This page covers `internal` access. The `internal` keyword is also part of the [`protected internal`](./protected-internal.md) access modifier. - -Internal types or members are accessible only within files in the same [assembly](../../../standard/assembly/index.md), as in this example: - -```csharp + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +> [!NOTE] +> This article covers `internal` access. The `internal` keyword is also part of the [`protected internal`](./protected-internal.md) access modifier. + +You can access internal types or members only within files in the same [assembly](../../../standard/assembly/index.md), as shown in the following example: + +```csharp public class BaseClass -{ +{ // Only accessible within the same assembly. internal static int x = 0; -} -``` +} +``` -For a comparison of `internal` with the other access modifiers, see [Accessibility Levels](./accessibility-levels.md) and [Access Modifiers](../../programming-guide/classes-and-structs/access-modifiers.md). +For a comparison of `internal` with the other access modifiers, see [Accessibility Levels](./accessibility-levels.md) and [Access Modifiers](../../programming-guide/classes-and-structs/access-modifiers.md). An `assembly` is an executable or dynamic link library (DLL) produced from compiling one or more source files. For more information about assemblies, see [Assemblies in .NET](../../../standard/assembly/index.md). -A common use of internal access is in component-based development because it enables a group of components to cooperate in a private manner without being exposed to the rest of the application code. For example, a framework for building graphical user interfaces could provide `Control` and `Form` classes that cooperate by using members with internal access. Since these members are internal, they are not exposed to code that is using the framework. +A common use of internal access is in component-based development because it enables a group of components to cooperate in a private manner without being exposed to the rest of the application code. For example, a framework for building graphical user interfaces could provide `Control` and `Form` classes that cooperate by using members with internal access. Since these members are internal, they aren't exposed to code that uses the framework. + +It's an error to reference a type or a member with internal access outside the assembly where you defined it. -It is an error to reference a type or a member with internal access outside the assembly within which it was defined. +## Examples -## Example 1 +This example contains two files, `Assembly1.cs` and `Assembly1_a.cs`. The first file contains an internal base class, `BaseClass`. In the second file, an attempt to instantiate `BaseClass` produces an error. - This example contains two files, `Assembly1.cs` and `Assembly1_a.cs`. The first file contains an internal base class, `BaseClass`. In the second file, an attempt to instantiate `BaseClass` will produce an error. - -```csharp -// Assembly1.cs -// Compile with: /target:library +```csharp +// Assembly1.cs +// Compile with: /target:library internal class BaseClass -{ - public static int intM = 0; -} -``` - -```csharp -// Assembly1_a.cs -// Compile with: /reference:Assembly1.dll +{ + public static int intM = 0; +} +``` + +```csharp +// Assembly1_a.cs +// Compile with: /reference:Assembly1.dll class TestAccess -{ +{ static void Main() - { - var myBase = new BaseClass(); // CS0122 - } -} -``` - -## Example 2 - - In this example, use the same files you used in example 1, and change the accessibility level of `BaseClass` to `public`. Also change the accessibility level of the member `intM` to `internal`. In this case, you can instantiate the class, but you cannot access the internal member. - -```csharp -// Assembly2.cs -// Compile with: /target:library + { + var myBase = new BaseClass(); // CS0122 + } +} +``` + +In this example, use the same files you used in the first example, but change the accessibility level of `BaseClass` to `public`. Also change the accessibility level of the member `intM` to `internal`. In this case, you can instantiate the class, but you can't access the internal member. + +```csharp +// Assembly2.cs +// Compile with: /target:library public class BaseClass -{ - internal static int intM = 0; -} -``` - -```csharp -// Assembly2_a.cs -// Compile with: /reference:Assembly2.dll +{ + internal static int intM = 0; +} +``` + +```csharp +// Assembly2_a.cs +// Compile with: /reference:Assembly2.dll public class TestAccess -{ +{ static void Main() - { - var myBase = new BaseClass(); // Ok. - BaseClass.intM = 444; // CS0117 - } -} -``` - -## C# Language Specification + { + var myBase = new BaseClass(); // Ok. + BaseClass.intM = 444; // CS0117 + } +} +``` + +## C# Language Specification For more information, see [Declared accessibility](~/_csharpstandard/standard/basic-concepts.md#752-declared-accessibility) in the [C# Language Specification](~/_csharpstandard/standard/README.md). The language specification is the definitive source for C# syntax and usage. - + ## See also - [C# Keywords](./index.md) diff --git a/docs/csharp/language-reference/keywords/into.md b/docs/csharp/language-reference/keywords/into.md index f56dbe422f85e..c77131dd9b018 100644 --- a/docs/csharp/language-reference/keywords/into.md +++ b/docs/csharp/language-reference/keywords/into.md @@ -1,27 +1,26 @@ --- description: "into - C# Reference" title: "into keyword" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "into_CSharpKeyword" - "into" helpviewer_keywords: - "into keyword [C#]" -ms.assetid: 81ec62c1-f0b1-4755-8a31-959876e77f65 --- # into (C# Reference) -The `into` contextual keyword can be used to create a temporary identifier to store the results of a [group](group-clause.md), [join](join-clause.md) or [select](select-clause.md) clause into a new identifier. This identifier can itself be a generator for additional query commands. When used in a `group` or `select` clause, the use of the new identifier is sometimes referred to as a *continuation*. +Use the `into` contextual keyword to create a temporary identifier that stores the results of a [`group`](group-clause.md), [`join`](join-clause.md), or [`select`](select-clause.md) clause. This identifier can act as a generator for additional query commands. When you use the new identifier in a `group` or `select` clause, it's sometimes called a *continuation*. -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -The following example shows the use of the `into` keyword to enable a temporary identifier `fruitGroup` which has an inferred type of `IGrouping`. By using the identifier, you can invoke the method on each group and select only those groups that contain two or more words. +The following example shows how to use the `into` keyword to create a temporary identifier named `fruitGroup`, which has an inferred type of `IGrouping`. By using this identifier, you can call the method on each group and select only those groups that contain two or more words. -[!code-csharp[cscsrefQueryKeywords#18](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Into.cs#18)] +:::code language="csharp" source="./snippets/into.cs" id="18"::: -The use of `into` in a `group` clause is only necessary when you want to perform additional query operations on each group. For more information, see [group clause](group-clause.md). +You only need to use `into` in a `group` clause when you want to perform additional query operations on each group. For more information, see [group clause](group-clause.md). -For an example of the use of `into` in a `join` clause, see [join clause](join-clause.md). +For an example of using `into` in a `join` clause, see [join clause](join-clause.md). ## See also diff --git a/docs/csharp/language-reference/keywords/join-clause.md b/docs/csharp/language-reference/keywords/join-clause.md index fc0433d3f96e8..011c7ac9cb296 100644 --- a/docs/csharp/language-reference/keywords/join-clause.md +++ b/docs/csharp/language-reference/keywords/join-clause.md @@ -1,32 +1,31 @@ --- description: "join clause - C# Reference" title: "join clause" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "join" - "join_CSharpKeyword" helpviewer_keywords: - "join clause [C#]" - "join keyword [C#]" -ms.assetid: 76e9df84-092c-41a6-9537-c3f1cbd7f0fb --- # join clause (C# Reference) -The `join` clause is useful for associating elements from different source sequences that have no direct relationship in the object model. The only requirement is that the elements in each source share some value that can be compared for equality. For example, a food distributor might have a list of suppliers of a certain product, and a list of buyers. A `join` clause can be used, for example, to create a list of the suppliers and buyers of that product who are all in the same specified region. +Use the `join` clause to associate elements from different source sequences that have no direct relationship in the object model. The only requirement is that the elements in each source share some value that you can compare for equality. For example, a food distributor might have a list of suppliers of a certain product, and a list of buyers. You can use a `join` clause to create a list of the suppliers and buyers of that product who are all in the same specified region. -A `join` clause takes two source sequences as input. The elements in each sequence must either be or contain a property that can be compared to a corresponding property in the other sequence. The `join` clause compares the specified keys for equality by using the special `equals` keyword. All joins performed by the `join` clause are equijoins. The shape of the output of a `join` clause depends on the specific type of join you are performing. The following are three most common join types: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -- Inner join +A `join` clause takes two source sequences as input. The elements in each sequence must either be or contain a property that you can compare to a corresponding property in the other sequence. The `join` clause uses the special `equals` keyword to compare the specified keys for equality. All joins that the `join` clause performs are equijoins. The shape of the output of a `join` clause depends on the specific type of join you're performing. The following list shows the three most common join types: +- Inner join - Group join - - Left outer join ## Inner join -The following example shows a simple inner equijoin. This query produces a flat sequence of "product name / category" pairs. The same category string will appear in multiple elements. If an element from `categories` has no matching `products`, that category will not appear in the results. +The following example shows a simple inner equijoin. This query produces a flat sequence of "product name / category" pairs. The same category string appears in multiple elements. If an element from `categories` has no matching `products`, that category doesn't appear in the results. -[!code-csharp[cscsrefQueryKeywords#24](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Join.cs#24)] +:::code language="csharp" source="./snippets/join.cs" id="24"::: For more information, see [Perform inner joins](../../linq/standard-query-operators/join-operations.md). @@ -34,31 +33,31 @@ For more information, see [Perform inner joins](../../linq/standard-query-operat A `join` clause with an `into` expression is called a group join. -[!code-csharp[cscsrefQueryKeywords#25](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Join.cs#25)] +:::code language="csharp" source="./snippets/join.cs" id="25"::: A group join produces a hierarchical result sequence, which associates elements in the left source sequence with one or more matching elements in the right side source sequence. A group join has no equivalent in relational terms; it is essentially a sequence of object arrays. -If no elements from the right source sequence are found to match an element in the left source, the `join` clause will produce an empty array for that item. Therefore, the group join is still basically an inner-equijoin except that the result sequence is organized into groups. +If no elements from the right source sequence match an element in the left source, the `join` clause produces an empty array for that item. Therefore, the group join is still basically an inner-equijoin except that the result sequence is organized into groups. -If you just select the results of a group join, you can access the items, but you cannot identify the key that they match on. Therefore, it is generally more useful to select the results of the group join into a new type that also has the key name, as shown in the previous example. +If you just select the results of a group join, you can access the items, but you can't identify the key that they match on. Therefore, it's generally more useful to select the results of the group join into a new type that also has the key name, as shown in the previous example. You can also, of course, use the result of a group join as the generator of another subquery: -[!code-csharp[cscsrefQueryKeywords#26](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Join.cs#26)] +:::code language="csharp" source="./snippets/join.cs" id="26"::: For more information, see [Perform grouped joins](../../linq/standard-query-operators/join-operations.md). ## Left outer join -In a left outer join, all the elements in the left source sequence are returned, even if no matching elements are in the right sequence. To perform a left outer join in LINQ, use the `DefaultIfEmpty` method in combination with a group join to specify a default right-side element to produce if a left-side element has no matches. You can use `null` as the default value for any reference type, or you can specify a user-defined default type. In the following example, a user-defined default type is shown: +In a left outer join, the query returns all the elements in the left source sequence, even if no matching elements are in the right sequence. To perform a left outer join in LINQ, use the `DefaultIfEmpty` method in combination with a group join to specify a default right-side element to produce if a left-side element has no matches. You can use `null` as the default value for any reference type, or you can specify a user-defined default type. In the following example, a user-defined default type is shown: -[!code-csharp[cscsrefQueryKeywords#27](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Join.cs#27)] +:::code language="csharp" source="./snippets/join.cs" id="27"::: For more information, see [Perform left outer joins](../../linq/standard-query-operators/join-operations.md). ## The equals operator -A `join` clause performs an equijoin. In other words, you can only base matches on the equality of two keys. Other types of comparisons such as "greater than" or "not equals" are not supported. To make clear that all joins are equijoins, the `join` clause uses the `equals` keyword instead of the `==` operator. The `equals` keyword can only be used in a `join` clause and it differs from the `==` operator in some important ways. When comparing strings, `equals` has an overload to compare by value and the operator `==` uses reference equality. When both sides of comparison have identical string variables, `equals` and `==` reach the same result: true. That's because, when a program declares two or more equivalent string variables, the compiler stores all of them in the same location. This is known as *interning*. Another important difference is the null comparison: `null equals null` is evaluated as false with `equals` operator, instead of `==` operator that evaluates it as true. Lastly, the scoping behavior is different: with `equals`, the left key consumes the outer source sequence, and the right key consumes the inner source. The outer source is only in scope on the left side of `equals` and the inner source sequence is only in scope on the right side. +A `join` clause performs an equijoin. In other words, you can only base matches on the equality of two keys. Other types of comparisons such as "greater than" or "not equals" aren't supported. To make clear that all joins are equijoins, the `join` clause uses the `equals` keyword instead of the `==` operator. The `equals` keyword can only be used in a `join` clause and it differs from the `==` operator in some important ways. When comparing strings, `equals` has an overload to compare by value and the operator `==` uses reference equality. When both sides of comparison have identical string variables, `equals` and `==` reach the same result: true. That's because, when a program declares two or more equivalent string variables, the compiler stores all of them in the same location. This is known as *interning*. Another important difference is the null comparison: `null equals null` is evaluated as false with `equals` operator, instead of `==` operator that evaluates it as true. Lastly, the scoping behavior is different: with `equals`, the left key consumes the outer source sequence, and the right key consumes the inner source. The outer source is only in scope on the left side of `equals` and the inner source sequence is only in scope on the right side. ## Non-equijoins @@ -66,23 +65,23 @@ You can perform non-equijoins, cross joins, and other custom join operations by ## Joins on object collections vs. relational tables -In a LINQ query expression, join operations are performed on object collections. Object collections cannot be "joined" in exactly the same way as two relational tables. In LINQ, explicit `join` clauses are only required when two source sequences are not tied by any relationship. When working with [!INCLUDE[vbtecdlinq](~/includes/vbtecdlinq-md.md)], foreign key tables are represented in the object model as properties of the primary table. For example, in the Northwind database, the Customer table has a foreign key relationship with the Orders table. When you map the tables to the object model, the Customer class has an Orders property that contains the collection of Orders associated with that Customer. In effect, the join has already been done for you. +In a LINQ query expression, you perform join operations on object collections. You can't join object collections in exactly the same way as two relational tables. In LINQ, you only need explicit `join` clauses when two source sequences don't have any relationship. When you work with [!INCLUDE[vbtecdlinq](~/includes/vbtecdlinq-md.md)], the object model represents foreign key tables as properties of the primary table. For example, in the Northwind database, the Customer table has a foreign key relationship with the Orders table. When you map the tables to the object model, the Customer class has an `Orders` property that contains the collection of `Orders` associated with that Customer. In effect, the join is already done for you. For more information about querying across related tables in the context of [!INCLUDE[vbtecdlinq](~/includes/vbtecdlinq-md.md)], see [How to: Map Database Relationships](../../../framework/data/adonet/sql/linq/how-to-map-database-relationships.md). ## Composite keys -You can test for equality of multiple values by using a composite key. For more information, see [Join by using composite keys](../../linq/standard-query-operators/join-operations.md). Composite keys can be also used in a `group` clause. +You can test for equality of multiple values by using a composite key. For more information, see [Join by using composite keys](../../linq/standard-query-operators/join-operations.md). You can also use composite keys in a `group` clause. ## Example The following example compares the results of an inner join, a group join, and a left outer join on the same data sources by using the same matching keys. Some extra code is added to these examples to clarify the results in the console display. -[!code-csharp[cscsrefQueryKeywords#23](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Join.cs#23)] +:::code language="csharp" source="./snippets/join.cs" id="23"::: ## Remarks -A `join` clause that is not followed by `into` is translated into a method call. A `join` clause that is followed by `into` is translated to a method call. +A `join` clause that isn't followed by `into` translates into a method call. A `join` clause that is followed by `into` translates to a method call. ## See also diff --git a/docs/csharp/language-reference/keywords/let-clause.md b/docs/csharp/language-reference/keywords/let-clause.md index f20a52cd33deb..8c94d1230f257 100644 --- a/docs/csharp/language-reference/keywords/let-clause.md +++ b/docs/csharp/language-reference/keywords/let-clause.md @@ -1,28 +1,26 @@ --- description: "let clause - C# Reference" title: "let clause" -ms.date: 07/20/2015 +ms.date: 01/21/2026 f1_keywords: - "let_CSharpKeyword" - "let" helpviewer_keywords: - "let keyword [C#]" - "let clause [C#]" -ms.assetid: 13c9c1a4-ce57-48ef-8e1b-4c2a59b99fb4 --- -# let clause (C# Reference) +# `let` clause (C# Reference) -In a query expression, it's sometimes useful to store the result of a subexpression in order to use it in subsequent clauses. You can do this with the `let` keyword, which creates a new range variable and initializes it with the result of the expression you supply. Once initialized with a value, the range variable can't be used to store another value. However, if the range variable holds a queryable type, it can be queried. +In a query expression, it can be useful to store the result of a subexpression so you can use it in later clauses. Use the `let` keyword to create a new range variable and initialize it with the result of an expression. After you initialize the range variable with a value, you can't assign it another value. However, if the range variable holds a queryable type, you can query it. -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -In the following example `let` is used in two ways: +In the following example, `let` is used in two ways: -1. To create an enumerable type that can itself be queried. +1. It creates an enumerable type that you can query. +1. It enables the query to call `ToLower` only one time on the range variable `word`. Without using `let`, you'd have to call `ToLower` in each predicate in the `where` clause. -2. To enable the query to call `ToLower` only one time on the range variable `word`. Without using `let`, you would have to call `ToLower` in each predicate in the `where` clause. - -[!code-csharp[cscsrefQueryKeywords#28](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Let.cs#28)] +:::code language="csharp" source="./snippets/let.cs" id="28"::: ## See also diff --git a/docs/csharp/language-reference/keywords/method-parameters.md b/docs/csharp/language-reference/keywords/method-parameters.md index 7089434872abe..6b75e566c0a90 100644 --- a/docs/csharp/language-reference/keywords/method-parameters.md +++ b/docs/csharp/language-reference/keywords/method-parameters.md @@ -1,7 +1,7 @@ --- title: "Method parameters and modifiers" description: "Parameter modifiers enable pass-by-reference semantics, with distinctions for read-only, and `out` parameters. The `params` modifier allows optional arguments." -ms.date: 11/19/2024 +ms.date: 01/22/2026 helpviewer_keywords: - "methods [C#], parameters" - "method parameters [C#]" @@ -9,11 +9,13 @@ helpviewer_keywords: --- # Method parameters and modifiers -By default, arguments in C# are passed to functions *by value*. That means a copy of the variable is passed to the method. For value (`struct`) types, a copy of the *value* is passed to the method. For reference (`class`) types, a copy of the *reference* is passed to the method. Parameter modifiers enable you to pass arguments *by reference*. +By default, C# passes arguments to functions *by value*. This approach passes a copy of the variable to the method. For value (`struct`) types, the method gets a copy of the *value*. For reference (`class`) types, the method gets a copy of the *reference*. You can use parameter modifiers to pass arguments *by reference*. -Because a struct is a [value type](../builtin-types/value-types.md), the method receives and operates on a copy of the argument when you pass a struct by value to a method. The method has no access to the original struct in the calling method and therefore can't change it in any way. The method can change only the copy. +Because a struct is a [value type](../builtin-types/value-types.md), passing a struct by value to a method sends a copy of the argument to the method. The method works with this copy. The method can't access the original struct in the calling method and can't change it. The method can change only the copy. -A class instance is a [reference type](reference-types.md) not a value type. When a reference type is passed by value to a method, the method receives a copy of the reference to the instance. Both variables refer to the same object. The parameter is a copy of the reference. The called method can't reassign the instance in the calling method. However, the called method can use the copy of the reference to access the instance members. If the called method changes an instance member, the calling method also sees those changes since it references the same instance. +A class instance is a [reference type](reference-types.md), not a value type. When you pass a reference type by value to a method, the method gets a copy of the reference to the instance. Both variables refer to the same object. The parameter is a copy of the reference. The called method can't reassign the instance in the calling method. However, the called method can use the copy of the reference to access the instance members. If the called method changes an instance member, the calling method also sees those changes since it references the same instance. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] ## Pass by value and pass by reference @@ -21,11 +23,11 @@ All the examples in this section use the following two `record` types to illustr :::code language="csharp" source="./snippets/PassParameters.cs" id="DataTypes"::: -The output of the following example illustrates the difference between passing a struct type by value and passing a class type by value. Both `Mutate` methods change property values of its argument. When the parameter is a `struct` type, those changes are made to a copy of the argument's data. When the parameter is a `class` type, those changes are made to the instance referred to by the argument: +The output of the following example illustrates the difference between passing a struct type by value and passing a class type by value. Both `Mutate` methods change property values of their argument. When the parameter is a `struct` type, those changes affect a copy of the argument's data. When the parameter is a `class` type, those changes affect the instance referred to by the argument: :::code language="csharp" source="./snippets/PassParameters.cs" id="PassTypesByValue"::: -The `ref` modifier is one way to pass arguments *by reference* to methods. The following code follows the preceding example, but passes parameters by reference. The modifications made to the `struct` type are visible in the calling method when the struct is passed by reference. There's no semantic change when a reference type is passed by reference: +The `ref` modifier is one way to pass arguments *by reference* to methods. The following code replicates the preceding example, but passes parameters by reference. The modifications made to the `struct` type are visible in the calling method when the struct is passed by reference. There's no semantic change when a reference type is passed by reference: :::code language="csharp" source="./snippets/PassParameters.cs" id="PassTypesByReference"::: @@ -33,7 +35,7 @@ The preceding examples modified properties of a parameter. A method can also rea :::code language="csharp" source="./snippets/PassParameters.cs" id="PassByValueReassignment"::: -The preceding sample shows that when you reassign a parameter to a new value, that change isn't visible from the calling method, regardless of whether the type is a value type or a reference type. The following example shows the behavior when you reassign a parameter that has been passed by reference: +The preceding sample shows that when you reassign a parameter to a new value, that change isn't visible from the calling method, regardless of whether the type is a value type or a reference type. The following example shows the behavior when you reassign a parameter that the method received by reference: :::code language="csharp" source="./snippets/PassParameters.cs" id="PassByReferenceReassignment"::: @@ -41,7 +43,7 @@ The preceding example shows how reassigning the value of a parameter that is pas ## Safe context of references and values -Methods can store the values of parameters in fields. When parameters are passed by value, that's usually safe. Values are copied, and reference types are reachable when stored in a field. Passing parameters by reference safely requires the compiler to define when it's safe to assign a reference to a new variable. For every expression, the compiler defines a *safe context* that bounds access to an expression or variable. The compiler uses two scopes: *safe-context* and *ref-safe-context*. +Methods can store the values of parameters in fields. When you pass parameters by value, it's usually safe. The method copies values, and reference types are reachable when the method stores them in a field. Passing parameters by reference safely requires the compiler to define when it's safe to assign a reference to a new variable. For every expression, the compiler defines a *safe context* that bounds access to an expression or variable. The compiler uses two scopes: *safe-context* and *ref-safe-context*. - The *safe-context* defines the scope where any expression can be safely accessed. - The *ref-safe-context* defines the scope where a *reference* to any expression can be safely accessed or modified. @@ -50,16 +52,16 @@ Informally, you can think of these scopes as the mechanism to ensure your code n ## Reference parameters -You apply one of the following modifiers to a parameter declaration to pass arguments by reference instead of by value: +To pass arguments by reference instead of by value, use one of the following modifiers in a parameter declaration: -- [`ref`](#ref-parameter-modifier): The argument must be initialized before calling the method. The method can assign a new value to the parameter, but isn't required to do so. -- [`out`](#out-parameter-modifier): The calling method isn't required to initialize the argument before calling the method. The method must assign a value to the parameter. -- [`ref readonly`](#ref-readonly-modifier): The argument must be initialized before calling the method. The method can't assign a new value to the parameter. -- [`in`](#in-parameter-modifier): The argument must be initialized before calling the method. The method can't assign a new value to the parameter. The compiler might create a temporary variable to hold a copy of the argument to `in` parameters. +- [`ref`](#ref-parameter-modifier): Initialize the argument before calling the method. The method can assign a new value to the parameter, but it isn't required to. +- [`out`](#out-parameter-modifier): The calling method doesn't need to initialize the argument before calling the method. The method must assign a value to the parameter. +- [`ref readonly`](#ref-readonly-modifier): Initialize the argument before calling the method. The method can't assign a new value to the parameter. +- [`in`](#in-parameter-modifier): Initialize the argument before calling the method. The method can't assign a new value to the parameter. The compiler might create a temporary variable to hold a copy of the argument to `in` parameters. -A parameter that is passed by reference is a *reference variable*. It doesn't have its own value. Instead, it refers to a different variable called its *referent*. Reference variables can be [ref reassigned](../operators/assignment-operator.md#ref-assignment), which changes its referent. +A parameter that's passed by reference is a *reference variable*. It doesn't have its own value. Instead, it refers to a different variable called its *referent*. You can [ref reassign](../operators/assignment-operator.md#ref-assignment) reference variables, which changes their referent. -Members of a class can't have signatures that differ only by `ref`, `ref readonly`, `in`, or `out`. A compiler error occurs if the only difference between two members of a type is that one of them has a `ref` parameter and the other has an `out`, `ref readonly`, or `in` parameter. However, methods can be overloaded when one method has a `ref`, `ref readonly`, `in`, or `out` parameter and the other has a parameter that is passed by value, as shown in the following example. In other situations that require signature matching, such as hiding or overriding, `in`, `ref`, `ref readonly`, and `out` are part of the signature and don't match each other. +Members of a class can't have signatures that differ only by `ref`, `ref readonly`, `in`, or `out`. A compiler error occurs if the only difference between two members of a type is that one member has a `ref` parameter and the other member has an `out`, `ref readonly`, or `in` parameter. However, you can overload methods when one method has a `ref`, `ref readonly`, `in`, or `out` parameter and the other method has a parameter that's passed by value, as shown in the following example. In other situations that require signature matching, such as hiding or overriding, `in`, `ref`, `ref readonly`, and `out` are part of the signature and don't match each other. When a parameter has one of the preceding modifiers, the corresponding argument can have a compatible modifier: @@ -73,7 +75,7 @@ When you use these modifiers, they describe how the argument is used: - `ref` means the method can read or write the value of the argument. - `out` means the method sets the value of the argument. - `ref readonly` means the method reads, but can't write the value of the argument. The argument *should* be passed by reference. -- `in` means the method reads, but can't write the value of the argument. The argument will be passed by reference or through a temporary variable. +- `in` means the method reads, but can't write the value of the argument. The argument is passed by reference or through a temporary variable. You can't use the previous parameter modifiers in the following kinds of methods: @@ -87,7 +89,7 @@ You can't use the previous parameter modifiers in the following kinds of methods - The `ref readonly` and `in` keywords can't be used unless the first argument is a `struct`. - The `ref readonly` and `in` keywords can't be used on any generic type, even when constrained to be a struct. -Properties aren't variables. They're methods. Properties can't be arguments for `ref` parameters. +Properties aren't variables. They're methods. You can't use properties as arguments for `ref` parameters. ### `ref` parameter modifier @@ -95,7 +97,7 @@ To use a `ref` parameter, both the method definition and the calling method must :::code language="csharp" source="snippets/RefParameterModifier.cs" id="Snippet1"::: -An argument that is passed to a `ref` parameter must be initialized before it's passed. +You must initialize an argument before you pass it to a `ref` parameter. ### `out` parameter modifier @@ -103,7 +105,7 @@ To use an `out` parameter, both the method definition and the calling method mus :::code language="csharp" source="snippets/RefParameterModifier.cs" id="OutVariableExample"::: -Variables passed as `out` arguments don't have to be initialized before being passed in a method call. However, the called method is required to assign a value before the method returns. +You don't need to initialize variables passed as `out` arguments before the method call. However, the called method must assign a value before it returns. [Deconstruct methods](../../fundamentals/functional/deconstruct.md) declare their parameters with the `out` modifier to return multiple values. Other methods can return [value tuples](../builtin-types/value-tuples.md) for multiple return values. @@ -115,11 +117,11 @@ You can also declare an implicitly typed local variable. ### `ref readonly` modifier -The `ref readonly` modifier must be present in the method declaration. A modifier at the call site is optional. Either the `in` or `ref` modifier can be used. The `ref readonly` modifier isn't valid at the call site. Which modifier you use at the call site can help describe characteristics of the argument. You can only use `ref` if the argument is a variable, and is writable. You can only use `in` when the argument is a variable. It might be writable, or readonly. You can't add either modifier if the argument isn't a variable, but is an expression. The following examples show these conditions. The following method uses the `ref readonly` modifier to indicate that a large struct should be passed by reference for performance reasons: +The method declaration requires the `ref readonly` modifier. A modifier at the call site is optional. You can use either the `in` or `ref` modifier. The `ref readonly` modifier isn't valid at the call site. The modifier you use at the call site can help describe characteristics of the argument. You can use `ref` only if the argument is a variable and is writable. You can use `in` only when the argument is a variable. The variable might be writable or readonly. You can't add either modifier if the argument isn't a variable but is an expression. The following examples show these conditions. The following method uses the `ref readonly` modifier to indicate that a large struct should be passed by reference for performance reasons: :::code language="csharp" source="snippets/RefParameterModifier.cs" id="ByReadonlyRefExample"::: -You can call the method using the `ref` or `in` modifier. If you omit the modifier, the compiler issues a warning. When the argument is an expression, not a variable, you can't add the `in` or `ref` modifiers, so you should suppress the warning: +You can call the method by using the `ref` or `in` modifier. If you omit the modifier, the compiler issues a warning. When the argument is an expression, not a variable, you can't add the `in` or `ref` modifiers, so you should suppress the warning: :::code language="csharp" source="snippets/RefParameterModifier.cs" id="ByReadonlyRefExampleCall"::: @@ -133,9 +135,9 @@ The `in` modifier is required in the method declaration but unnecessary at the c :::code language="csharp" source="snippets/RefParameterModifier.cs" id="InParameterModifier"::: -The `in` modifier allows the compiler to create a temporary variable for the argument and pass a readonly reference to that argument. The compiler always creates a temporary variable when the argument must be converted, when there's an [implicit conversion](~/_csharpstandard/standard/conversions.md#102-implicit-conversions) from the argument type, or when the argument is a value that isn't a variable. For example, when the argument is a literal value, or the value returned from a property accessor. When your API requires that the argument be passed by reference, choose the `ref readonly` modifier instead of the `in` modifier. +The `in` modifier enables the compiler to create a temporary variable for the argument and pass a readonly reference to that argument. The compiler always creates a temporary variable when the argument must be converted, when there's an [implicit conversion](~/_csharpstandard/standard/conversions.md#102-implicit-conversions) from the argument type, or when the argument is a value that isn't a variable. For example, when the argument is a literal value, or the value returned from a property accessor. When your API requires that the argument be passed by reference, choose the `ref readonly` modifier instead of the `in` modifier. -Methods that are defined using `in` parameters potentially gain performance optimization. Some `struct` type arguments might be large in size, and when methods are called in tight loops or critical code paths, the cost of copying those structures is substantial. Methods declare `in` parameters to specify that arguments can be passed by reference safely because the called method doesn't modify the state of that argument. Passing those arguments by reference avoids the (potentially) expensive copy. You explicitly add the `in` modifier at the call site to ensure the argument is passed by reference, not by value. Explicitly using `in` has the following two effects: +You can gain performance optimization by defining methods with `in` parameters. Some `struct` type arguments might be large in size, and when you call methods in tight loops or critical code paths, the cost of copying those structures is substantial. Declare `in` parameters to specify that you can safely pass arguments by reference because the called method doesn't modify the state of that argument. Passing those arguments by reference avoids the (potentially) expensive copy. You explicitly add the `in` modifier at the call site to ensure the argument is passed by reference, not by value. Explicitly using `in` has the following two effects: - Specifying `in` at the call site forces the compiler to select a method defined with a matching `in` parameter. Otherwise, when two methods differ only in the presence of `in`, the by value overload is a better match. - By specifying `in`, you declare your intent to pass an argument by reference. The argument used with `in` must represent a location that can be directly referred to. The same general rules for `out` and `ref` arguments apply: You can't use constants, ordinary properties, or other expressions that produce values. Otherwise, omitting `in` at the call site informs the compiler that it's fine to create a temporary variable to pass by read-only reference to the method. The compiler creates a temporary variable to overcome several restrictions with `in` arguments: @@ -189,36 +191,36 @@ Method(in i); // passed by readonly reference, explicitly using `in` The only method call where the argument is passed by reference is the final one. > [!NOTE] -> The preceding code uses `int` as the argument type for simplicity. Because `int` is no larger than a reference in most modern machines, there is no benefit to passing a single `int` as a readonly reference. +> The preceding code uses `int` as the argument type for simplicity. Because `int` is no larger than a reference in most modern machines, there's no benefit to passing a single `int` as a readonly reference. ## `params` modifier -No other parameters are permitted after the `params` keyword in a method declaration, and only one `params` keyword is permitted in a method declaration. +The parameter with the `params` keyword must be the last parameter in the method declaration. You can only use one `params` keyword in a method declaration. -The declared type of the `params` parameter must be a collection type. Recognized collection types are: +You must declare the `params` parameter as a collection type. Recognized collection types include: -- A single dimensional *array type* `T[]`, in which case the *element type* is `T`. +- A single-dimensional *array type* `T[]`, where the *element type* is `T`. - A *span type*: - `System.Span` - `System.ReadOnlySpan` - Here, the *element type* is `T`. -- A *type* with an accessible *create method* with a corresponding *element type*. The [*create method*](../operators/collection-expressions.md#collection-builder) is identified using the same attribute used for [collection expressions](../operators/collection-expressions.md). + In these types, the *element type* is `T`. +- A *type* with an accessible *create method* that has a corresponding *element type*. The [*create method*](../operators/collection-expressions.md#collection-builder) uses the same attribute as [collection expressions](../operators/collection-expressions.md). - A *struct* or *class type* that implements where: - - The *type* has a constructor that can be invoked with no arguments, and the constructor is at least as accessible as the declaring member. + - The *type* has a constructor that you can invoke without arguments, and the constructor is at least as accessible as the declaring member. - The *type* has an instance (not an extension) method `Add` where: - The method can be invoked with a single value argument. - If the method is generic, the type arguments can be inferred from the argument. - The method is at least as accessible as the declaring member. - Here, the *element type* is the *iteration type* of the *type*. + In this case, the *element type* is the *iteration type* of the *type*. - An *interface type*: - - - - - - Here, the *element type* is `T`. + In these types, the *element type* is `T`. -Before C# 13, the parameter must be a single dimensional array. +Before C# 13, you must use a single-dimensional array for the parameter. When you call a method with a `params` parameter, you can pass in: @@ -226,7 +228,7 @@ When you call a method with a `params` parameter, you can pass in: - A collection of arguments of the specified type. - No arguments. If you send no arguments, the length of the `params` list is zero. -The following example demonstrates various ways in which arguments can be sent to a `params` parameter. +The following example demonstrates various ways to send arguments to a `params` parameter. :::code language="csharp" source="snippets/ParameterModifiers.cs" id="ParamsModifierExamples"::: diff --git a/docs/csharp/language-reference/keywords/namespace.md b/docs/csharp/language-reference/keywords/namespace.md index fdea80074230f..6a67cef3da439 100644 --- a/docs/csharp/language-reference/keywords/namespace.md +++ b/docs/csharp/language-reference/keywords/namespace.md @@ -1,7 +1,7 @@ --- description: "Organize related types and functionality using the namespace keyword - C# Reference" title: "The namespace keyword" -ms.date: 11/22/2024 +ms.date: 01/22/2026 f1_keywords: - "namespace_CSharpKeyword" - "namespace" @@ -11,20 +11,22 @@ helpviewer_keywords: --- # The `namespace` keyword -The `namespace` keyword is used to declare a scope that contains a set of related objects. You can use a namespace to organize code elements and to create globally unique types. +Use the `namespace` keyword to declare a scope that contains a set of related objects. Use a namespace to organize code elements and to create globally unique types. :::code language="csharp" source="snippets/csrefKeywordsNamespace.cs" id="Snippet1"::: -*File scoped namespace declarations* enable you to declare that all types in a file are in a single namespace. The following example is similar to the previous example, but uses a file scoped namespace declaration: +*File scoped namespace declarations* enable you to declare that all types in a file are in a single namespace. The following example is similar to the previous example but uses a file scoped namespace declaration: :::code language="csharp" source="snippets/filescopednamespace.cs" ::: -## Using Statements in File Scoped Namespaces +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +## Using statements in file-scoped namespaces When you use *file-scoped namespaces*, the placement of `using` statements affects their scope within the file. File-scoped namespaces lower to the equivalent traditional namespace declaration that ends with a closing bracket at the end of the file. This behavior determines where `using` directives are applied as follows: -- If the `using` statements are placed before the file-scoped namespace declaration, they're treated as being outside of the namespace and are interpreted as fully qualified namespaces. -- If the `using` statements are placed after the file-scoped namespace declaration, they're scoped within the namespace itself. +- If you place the `using` statements before the file-scoped namespace declaration, they're treated as being outside of the namespace and are interpreted as fully qualified namespaces. +- If you place the `using` statements after the file-scoped namespace declaration, they're scoped within the namespace itself. For example: diff --git a/docs/csharp/language-reference/keywords/new-constraint.md b/docs/csharp/language-reference/keywords/new-constraint.md index b7824b7ab4ab5..25add4e78a559 100644 --- a/docs/csharp/language-reference/keywords/new-constraint.md +++ b/docs/csharp/language-reference/keywords/new-constraint.md @@ -1,27 +1,28 @@ --- description: "new constraint - C# Reference" title: "new constraint" -ms.date: 07/20/2015 +ms.date: 01/22/2026 helpviewer_keywords: - "new constraint keyword [C#]" -ms.assetid: 58850b64-cb97-4136-be50-1f3bc7fc1da9 --- # new constraint (C# Reference) -The `new` constraint specifies that a type argument in a generic class or method declaration must have a public parameterless constructor. To use the `new` constraint, the type cannot be abstract. +The `new` constraint specifies that a type argument in a generic class or method declaration must have a public parameterless constructor. To use the `new` constraint, the type can't be abstract. Apply the `new` constraint to a type parameter when a generic class creates new instances of the type, as shown in the following example: -[!code-csharp[csrefKeywordsOperator#5](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperators.cs#5)] +:::code language="csharp" source="./snippets/csrefKeywordsOperators.cs" id="5"::: -When you use the `new()` constraint with other constraints, it must be specified last: +When you use the `new()` constraint with other constraints, you must specify it last: -[!code-csharp[csrefKeywordsOperator#6](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperators.cs#6)] +:::code language="csharp" source="./snippets/csrefKeywordsOperators.cs" id="6"::: For more information, see [Constraints on Type Parameters](../../programming-guide/generics/constraints-on-type-parameters.md). You can also use the `new` keyword to [create an instance of a type](../operators/new-operator.md) or as a [member declaration modifier](new-modifier.md). +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + ## C# language specification For more information, see the [Type parameter constraints](~/_csharpstandard/standard/classes.md#1525-type-parameter-constraints) section of the [C# language specification](~/_csharpstandard/standard/README.md). diff --git a/docs/csharp/language-reference/keywords/new-modifier.md b/docs/csharp/language-reference/keywords/new-modifier.md index 13ad27d9e7214..88b2c0b9863e5 100644 --- a/docs/csharp/language-reference/keywords/new-modifier.md +++ b/docs/csharp/language-reference/keywords/new-modifier.md @@ -1,46 +1,47 @@ --- description: "new modifier - C# Reference" title: "new modifier" -ms.date: 07/20/2015 +ms.date: 01/22/2026 helpviewer_keywords: - "new modifier keyword [C#]" -ms.assetid: a2e20856-33b9-4620-b535-a60dbce8349b --- # new modifier (C# Reference) -When used as a declaration modifier, the `new` keyword explicitly hides a member that is inherited from a base class. When you hide an inherited member, the derived version of the member replaces the base class version. This assumes that the base class version of the member is visible, as it would already be hidden if it were marked as `private` or, in some cases, `internal`. Although you can hide `public` or `protected` members without using the `new` modifier, you get a compiler warning. If you use `new` to explicitly hide a member, it suppresses this warning. +When you use the `new` keyword as a declaration modifier, you explicitly hide a member that a base class provides. When you hide an inherited member, the derived version of the member replaces the base class version. You can hide a member when the base class version is visible in the derived class. The base class version isn't visible if it's marked as `private` or, in some cases, `internal`. Although you can hide `public` or `protected` members without using the `new` modifier, you get a compiler warning. If you use `new` to explicitly hide a member, it suppresses this warning. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] You can also use the `new` keyword to [create an instance of a type](../operators/new-operator.md) or as a [generic type constraint](./new-constraint.md). To hide an inherited member, declare it in the derived class by using the same member name, and modify it with the `new` keyword. For example: -[!code-csharp[csrefKeywordsOperator#8](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperators.cs#8)] +:::code language="csharp" source="./snippets/csrefKeywordsOperators.cs" id="8"::: -In this example, `BaseC.Invoke` is hidden by `DerivedC.Invoke`. The field `x` is not affected because it is not hidden by a similar name. +In this example, `BaseC.Invoke` is hidden by `DerivedC.Invoke`. The field `x` isn't affected because it isn't hidden by a similar name. Name hiding through inheritance takes one of the following forms: -- Generally, a constant, field, property, or type that is introduced in a class or struct hides all base class members that share its name. There are special cases. For example, if you declare a new field with name `N` to have a type that is not invocable, and a base type declares `N` to be a method, the new field does not hide the base declaration in invocation syntax. For more information, see the [Member lookup](~/_csharpstandard/standard/expressions.md#125-member-lookup) section of the [C# language specification](~/_csharpstandard/standard/README.md). +- Generally, a constant, field, property, or type that you introduce in a class or struct hides all base class members that share its name. However, some special cases exist. For example, if you declare a new field with name `N` to have a type that isn't invocable, and a base type declares `N` to be a method, the new field doesn't hide the base declaration in invocation syntax. For more information, see the [Member lookup](~/_csharpstandard/standard/expressions.md#125-member-lookup) section of the [C# language specification](~/_csharpstandard/standard/README.md). -- A method introduced in a class or struct hides properties, fields, and types that share that name in the base class. It also hides all base class methods that have the same signature. +- A method that you introduce in a class or struct hides properties, fields, and types that share that name in the base class. It also hides all base class methods that have the same signature. -- An indexer introduced in a class or struct hides all base class indexers that have the same signature. +- An indexer that you introduce in a class or struct hides all base class indexers that have the same signature. -It is an error to use both `new` and [override](override.md) on the same member, because the two modifiers have mutually exclusive meanings. The `new` modifier creates a new member with the same name and causes the original member to become hidden. The `override` modifier extends the implementation for an inherited member. +It's an error to use both `new` and [override](override.md) on the same member, because the two modifiers have mutually exclusive meanings. The `new` modifier creates a new member with the same name and causes the original member to become hidden. The `override` modifier extends the implementation for an inherited member. -Using the `new` modifier in a declaration that does not hide an inherited member generates a warning. +Using the `new` modifier in a declaration that doesn't hide an inherited member generates a warning. ## Examples In this example, a base class, `BaseC`, and a derived class, `DerivedC`, use the same field name `x`, which hides the value of the inherited field. The example demonstrates the use of the `new` modifier. It also demonstrates how to access the hidden members of the base class by using their fully qualified names. -[!code-csharp[csrefKeywordsOperator#9](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperators.cs#9)] +:::code language="csharp" source="./snippets/csrefKeywordsOperators.cs" id="9"::: In this example, a nested class hides a class that has the same name in the base class. The example demonstrates how to use the `new` modifier to eliminate the warning message and how to access the hidden class members by using their fully qualified names. -[!code-csharp[csrefKeywordsOperator#10](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperators.cs#10)] +:::code language="csharp" source="./snippets/csrefKeywordsOperators.cs" id="10"::: -If you remove the `new` modifier, the program will still compile and run, but you will get the following warning: +If you remove the `new` modifier, the program still compiles and runs, but you get the following warning: ```text The keyword new is required on 'MyDerivedC.x' because it hides inherited member 'MyBaseC.x'. diff --git a/docs/csharp/language-reference/keywords/new.md b/docs/csharp/language-reference/keywords/new.md index 0b40427a4ad75..8986c982cec58 100644 --- a/docs/csharp/language-reference/keywords/new.md +++ b/docs/csharp/language-reference/keywords/new.md @@ -1,7 +1,7 @@ --- description: "new - C# Reference" title: "new keyword" -ms.date: 01/02/2024 +ms.date: 01/22/2026 f1_keywords: - "new" - "new_CSharpKeyword" @@ -9,9 +9,9 @@ helpviewer_keywords: - "new keyword [C#]" --- -# new (C# Reference) +# new (C# reference) -The `new` keyword is used as: +Use the `new` keyword as an operator, modifier, or constraint: - [new operator](../operators/new-operator.md) - [new modifier](new-modifier.md) diff --git a/docs/csharp/language-reference/keywords/null.md b/docs/csharp/language-reference/keywords/null.md index 6fd0667b19e8b..df8bd168d6687 100644 --- a/docs/csharp/language-reference/keywords/null.md +++ b/docs/csharp/language-reference/keywords/null.md @@ -1,21 +1,22 @@ --- description: "null keyword - C# Reference" title: "null keyword" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "null" - "null_CSharpKeyword" helpviewer_keywords: - "null keyword [C#]" -ms.assetid: fecb1c60-6232-4efe-87f7-9a86ba2e9119 --- # null (C# Reference) -The `null` keyword is a literal that represents a null reference, one that does not refer to any object. `null` is the default value of reference-type variables. Ordinary value types cannot be null, except for [nullable value types](../builtin-types/nullable-value-types.md). +The `null` keyword is a literal that represents a null reference, one that doesn't refer to any object. `null` is the default value of reference-type variables. Ordinary value types can't be null, except for [nullable value types](../builtin-types/nullable-value-types.md). + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] The following example demonstrates some behaviors of the `null` keyword: -[!code-csharp[csrefKeywordsLiteral#1](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsLiteral/CS/csrefKeywordsLiteral.cs#1)] +:::code language="csharp" source="./snippets/csrefKeywordsLiteral.cs" id="1"::: ## C# language specification diff --git a/docs/csharp/language-reference/keywords/on.md b/docs/csharp/language-reference/keywords/on.md index 5b2f4fbba8193..baf9c88827466 100644 --- a/docs/csharp/language-reference/keywords/on.md +++ b/docs/csharp/language-reference/keywords/on.md @@ -1,23 +1,22 @@ --- description: "on keyword - C# Reference" title: "on keyword" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "on_CSharpKeyword" - "on" helpviewer_keywords: - "on keyword [C#]" -ms.assetid: 06abc536-e07c-4e34-88c1-425208bdcb21 --- # on (C# Reference) -The `on` contextual keyword is used in the [join clause](join-clause.md) of a query expression to specify the join condition. +Use the `on` contextual keyword in the [join clause](join-clause.md) of a query expression to specify the join condition. -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -The following example shows the use of `on` in a `join` clause. +The following example shows how to use `on` in a `join` clause. -[!code-csharp[csrefKeywordsContextual#12](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/csrefKeywordsContextual.cs#12)] +:::code language="csharp" source="./snippets/csrefKeywordsContextual.cs" id="12"::: ## See also diff --git a/docs/csharp/language-reference/keywords/orderby-clause.md b/docs/csharp/language-reference/keywords/orderby-clause.md index f55a8bd904048..fb9552ff12394 100644 --- a/docs/csharp/language-reference/keywords/orderby-clause.md +++ b/docs/csharp/language-reference/keywords/orderby-clause.md @@ -1,34 +1,29 @@ --- description: "orderby clause - C# Reference" title: "orderby clause" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "orderby" - "orderby_CSharpKeyword" helpviewer_keywords: - "orderby clause [C#]" - "orderby keyword [C#]" -ms.assetid: 21f87f48-d69d-4e95-9a52-6fec47b37e1f --- # orderby clause (C# Reference) -In a query expression, the `orderby` clause causes the returned sequence or subsequence (group) to be sorted in either ascending or descending order. Multiple keys can be specified in order to perform one or more secondary sort operations. The sorting is performed by the default comparer for the type of the element. The default sort order is ascending. You can also specify a custom comparer. However, it is only available by using method-based syntax. For more information, see [Sorting Data](../../linq/standard-query-operators/sorting-data.md). +In a query expression, the `orderby` clause sorts the returned sequence or subsequence (group) in either ascending or descending order. You can specify multiple keys to perform one or more secondary sort operations. The default comparer for the type of the element performs the sorting. The default sort order is ascending. You can also specify a custom comparer, but you can only provide it by using method-based syntax. For more information, see [Sorting Data](../../linq/standard-query-operators/sorting-data.md). -## Example 1 +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] In the following example, the first query sorts the words in alphabetical order starting from A, and second query sorts the same words in descending order. (The `ascending` keyword is the default sort value and can be omitted.) -[!code-csharp[cscsrefQueryKeywords#20](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Orderby.cs#20)] - -## Example 2 +:::code language="csharp" source="./snippets/Orderby.cs" id="20"::: The following example performs a primary sort on the students' last names, and then a secondary sort on their first names. -[!code-csharp[cscsrefQueryKeywords#22](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Orderby.cs#22)] - -## Remarks +:::code language="csharp" source="./snippets/Orderby.cs" id="22"::: -At compile time, the `orderby` clause is translated to a call to the method. Multiple keys in the `orderby` clause translate to method calls. +At compile time, the `orderby` clause translates to a call to the method. Multiple keys in the `orderby` clause translate to method calls. ## See also diff --git a/docs/csharp/language-reference/keywords/out-generic-modifier.md b/docs/csharp/language-reference/keywords/out-generic-modifier.md index 580d58ce3db60..d5a133a15c626 100644 --- a/docs/csharp/language-reference/keywords/out-generic-modifier.md +++ b/docs/csharp/language-reference/keywords/out-generic-modifier.md @@ -1,46 +1,43 @@ --- description: "out keyword (generic modifier) - C# Reference" title: "out keyword (generic modifier)" -ms.date: 07/20/2015 +ms.date: 01/22/2026 helpviewer_keywords: - "covariance, out keyword [C#]" - "out keyword [C#]" -ms.assetid: f8c20dec-a8bc-426a-9882-4076b1db1e00 --- # out (generic modifier) (C# Reference) -For generic type parameters, the `out` keyword specifies that the type parameter is covariant. You can use the `out` keyword in generic interfaces and delegates. +For generic type parameters, the `out` keyword specifies that the type parameter is covariant. Use the `out` keyword in generic interfaces and delegates. -Covariance enables you to use a more derived type than that specified by the generic parameter. This allows for implicit conversion of classes that implement covariant interfaces and implicit conversion of delegate types. Covariance and contravariance are supported for reference types, but they are not supported for value types. +Covariance enables you to use a more derived type than the generic parameter specifies. This feature allows for implicit conversion of classes that implement covariant interfaces and implicit conversion of delegate types. Covariance and contravariance support reference types, but they don't support value types. -An interface that has a covariant type parameter enables its methods to return more derived types than those specified by the type parameter. For example, because in .NET Framework 4, in , type T is covariant, you can assign an object of the `IEnumerable(Of String)` type to an object of the `IEnumerable(Of Object)` type without using any special conversion methods. +An interface with a covariant type parameter enables its methods to return more derived types than those specified by the type parameter. For example, because in .NET, in , type T is covariant, you can assign an object of the `IEnumerable` type to an object of the `IEnumerable` type without using any special conversion methods. -A covariant delegate can be assigned another delegate of the same type, but with a more derived generic type parameter. +You can assign a covariant delegate to another delegate of the same type, but with a more derived generic type parameter. For more information, see [Covariance and Contravariance](../../programming-guide/concepts/covariance-contravariance/index.md). -## Example - covariant generic interface +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] The following example shows how to declare, extend, and implement a covariant generic interface. It also shows how to use implicit conversion for classes that implement a covariant interface. -[!code-csharp[csVarianceKeywords#3](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csvariancekeywords/cs/program.cs#3)] +:::code language="csharp" source="./snippets/variance.cs" id="3"::: -In a generic interface, a type parameter can be declared covariant if it satisfies the following conditions: +In a generic interface, declare a type parameter covariant if it satisfies the following conditions: -- The type parameter is used only as a return type of interface methods and not used as a type of method arguments. +- You use the type parameter only as a return type of interface methods and don't use it as a type of method arguments. - > [!NOTE] - > There is one exception to this rule. If in a covariant interface you have a contravariant generic delegate as a method parameter, you can use the covariant type as a generic type parameter for this delegate. For more information about covariant and contravariant generic delegates, see [Variance in Delegates](../../programming-guide/concepts/covariance-contravariance/variance-in-delegates.md) and [Using Variance for Func and Action Generic Delegates](../../programming-guide/concepts/covariance-contravariance/using-variance-for-func-and-action-generic-delegates.md). + > [!NOTE] + > There's one exception to this rule. If a covariant interface has a contravariant generic delegate as a method parameter, you can use the covariant type as a generic type parameter for this delegate. For more information about covariant and contravariant generic delegates, see [Variance in Delegates](../../programming-guide/concepts/covariance-contravariance/variance-in-delegates.md) and [Using Variance for Func and Action Generic Delegates](../../programming-guide/concepts/covariance-contravariance/using-variance-for-func-and-action-generic-delegates.md). -- The type parameter is not used as a generic constraint for the interface methods. - -## Example - covariant generic delegate +- You don't use the type parameter as a generic constraint for the interface methods. The following example shows how to declare, instantiate, and invoke a covariant generic delegate. It also shows how to implicitly convert delegate types. -[!code-csharp[csVarianceKeywords#4](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csvariancekeywords/cs/program.cs#4)] +:::code language="csharp" source="./snippets/variance.cs" id="4"::: -In a generic delegate, a type can be declared covariant if it is used only as a method return type and not used for method arguments. +In a generic delegate, declare a type covariant if you use it only as a method return type and not for method arguments. ## C# language specification diff --git a/docs/csharp/language-reference/keywords/out.md b/docs/csharp/language-reference/keywords/out.md index 7c7c36ef88e86..6db0d57a76d31 100644 --- a/docs/csharp/language-reference/keywords/out.md +++ b/docs/csharp/language-reference/keywords/out.md @@ -1,24 +1,24 @@ --- description: "out keyword - C# Reference" title: "out keyword" -ms.date: 03/01/2017 +ms.date: 01/22/2026 f1_keywords: - "out_CSharpKeyword" - "out" helpviewer_keywords: - "out [C#]" - "out keyword [C#]" -ms.assetid: 7e911a0c-3f98-4536-87be-d539b7536ca8 --- # out (C# Reference) -You can use the `out` keyword in two contexts: +Use the `out` keyword in two contexts: -- As a [parameter modifier](method-parameters.md#out-parameter-modifier), which lets you pass an argument to a method by reference rather than by value. +- As a [parameter modifier](method-parameters.md#out-parameter-modifier), which you use to pass an argument to a method by reference rather than by value. +- In [generic type parameter declarations](out-generic-modifier.md) for interfaces and delegates, which you use to specify that a type parameter is covariant. -- In [generic type parameter declarations](out-generic-modifier.md) for interfaces and delegates, which specifies that a type parameter is covariant. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -The `out` keyword is especially useful when a method needs to return more than one value since more than one `out` parameter can be used e.g. +The `out` parameter modifier is especially useful when a method needs to return more than one value since you can use more than one `out` parameter. For example, ```csharp public void Main() @@ -41,6 +41,6 @@ The `out` keyword is especially useful when a method needs to return more than o The following limitations apply to using the `out` keyword: -- `out` parameters are not allowed in asynchronous methods. -- `out` parameters are not allowed in iterator methods. -- Properties cannot be passed as `out` parameters. +- You can't use `out` parameters in asynchronous methods. +- You can't use `out` parameters in iterator methods. +- You can't pass properties as `out` parameters. diff --git a/docs/csharp/language-reference/keywords/override.md b/docs/csharp/language-reference/keywords/override.md index ba8204cb9b1d1..6f5ab6b4a4cc7 100644 --- a/docs/csharp/language-reference/keywords/override.md +++ b/docs/csharp/language-reference/keywords/override.md @@ -1,29 +1,30 @@ --- description: "override modifier - C# Reference" title: "override modifier" -ms.date: 10/22/2020 +ms.date: 01/22/2026 f1_keywords: - "override" - "override_CSharpKeyword" helpviewer_keywords: - "override keyword [C#]" -ms.assetid: dd1907a8-acf8-46d3-80b9-c2ca4febada8 --- # override (C# reference) -The `override` modifier is required to extend or modify the abstract or virtual implementation of an inherited method, property, indexer, or event. +Use the `override` modifier to extend or modify the abstract or virtual implementation of an inherited method, property, indexer, or event. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] In the following example, the `Square` class must provide an overridden implementation of `GetArea` because `GetArea` is inherited from the abstract `Shape` class: -[!code-csharp[csrefKeywordsModifiers#1](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#1)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="1"::: -An `override` method provides a new implementation of the method inherited from a base class. The method that is overridden by an `override` declaration is known as the overridden base method. An `override` method must have the same signature as the overridden base method. `override` methods support covariant return types. In particular, the return type of an `override` method can derive from the return type of the corresponding base method. +An `override` method provides a new implementation of the method inherited from a base class. An `override` method declaration provides a more specific implementation of the overridden base method. An `override` method must have the same signature as the overridden base method. `override` methods support covariant return types. In particular, the return type of an `override` method can derive from the return type of the corresponding base method. -You cannot override a non-virtual or static method. The overridden base method must be `virtual`, `abstract`, or `override`. +You can't override a non-virtual or static method. The overridden base method must be `virtual`, `abstract`, or `override`. -An `override` declaration cannot change the accessibility of the `virtual` method. Both the `override` method and the `virtual` method must have the same [access level modifier](access-modifiers.md). +An `override` declaration can't change the accessibility of the `virtual` method. Both the `override` method and the `virtual` method must have the same [access level modifier](access-modifiers.md). -You cannot use the `new`, `static`, or `virtual` modifiers to modify an `override` method. +You can't use the `new`, `static`, or `virtual` modifiers to modify an `override` method. An overriding property declaration must specify exactly the same access modifier, type, and name as the inherited property. Read-only overriding properties support covariant return types. The overridden property must be `virtual`, `abstract`, or `override`. @@ -31,9 +32,9 @@ For more information about how to use the `override` keyword, see [Versioning wi ## Example -This example defines a base class named `Employee`, and a derived class named `SalesEmployee`. The `SalesEmployee` class includes an extra field, `salesbonus`, and overrides the method `CalculatePay` in order to take it into account. +This example defines a base class named `Employee` and a derived class named `SalesEmployee`. The `SalesEmployee` class includes an extra field, `salesbonus`, and overrides the method `CalculatePay` to take the bonus into account. -[!code-csharp[csrefKeywordsModifiers#9](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#9)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="9"::: ## C# language specification diff --git a/docs/csharp/language-reference/keywords/partial-member.md b/docs/csharp/language-reference/keywords/partial-member.md index 7556ca6e8ada7..a895da3749302 100644 --- a/docs/csharp/language-reference/keywords/partial-member.md +++ b/docs/csharp/language-reference/keywords/partial-member.md @@ -1,7 +1,7 @@ --- description: "Partial members are members that can be declared in one partial type declaration and defined in a separate partial type declaration." title: "Partial members" -ms.date: 03/13/2025 +ms.date: 01/22/2026 f1_keywords: - "partialmethod_CSharpKeyword" helpviewer_keywords: @@ -16,6 +16,8 @@ A partial member has one *declaring declaration* and often one *implementing dec The `partial` keyword isn't allowed on static constructors, finalizers, or overloaded operators. Before C# 14, `partial` wasn't allowed on instance constructors or event declarations. Before C# 13, `partial` wasn't allowed on properties or indexers. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + A partial method isn't required to have an implementing declaration in the following cases: - It doesn't have any accessibility modifiers (including the default [`private`](../../language-reference/keywords/private.md)). @@ -43,7 +45,7 @@ The following example shows a declaring declaration and an implementing declarat The preceding example illustrates rules on how the two declarations are combined: -- *Signature matches*: In general, the signatures for the declaring and implementing declarations must match. This includes accessibility modifier on methods, properties, indexers, and individual accessors. It includes the parameter type and ref-kind modifiers on all parameters. The return type and any ref-kind modifier must match. Tuple member names must match. However, some rules are flexible: +- *Signature matches*: In general, the signatures for the declaring and implementing declarations must match. This rule includes the accessibility modifier on methods, properties, indexers, and individual accessors. It includes the parameter type and ref-kind modifiers on all parameters. The return type and any ref-kind modifier must match. Tuple member names must match. However, some rules are flexible: - The declaring and implementing declarations can have different [nullable](../compiler-options/language.md#nullable) annotations settings. Meaning that one can be *nullable oblivious* and the other *nullable enabled*. - Nullability differences that don't involve *oblivious nullability* generates a warning. - Default parameter values don't need to match. The compiler issues a warning if the implementing declaration of a method or indexer declares a default parameter value. diff --git a/docs/csharp/language-reference/keywords/partial-type.md b/docs/csharp/language-reference/keywords/partial-type.md index 51617b1b21ff0..4ef39fa773d98 100644 --- a/docs/csharp/language-reference/keywords/partial-type.md +++ b/docs/csharp/language-reference/keywords/partial-type.md @@ -1,7 +1,7 @@ --- description: "A partial type is a type declaration that allows you to split the declaration of the type into multiple files." title: "Partial type" -ms.date: 03/13/2025 +ms.date: 01/22/2026 f1_keywords: - "partialtype" - "partialtype_CSharpKeyword" @@ -10,7 +10,7 @@ helpviewer_keywords: --- # Partial type (C# Reference) -Partial type definitions allow for the definition of a class, struct, interface, or record to be split into multiple definitions. These multiple definitions can be in different files in the same project. One type declaration contains only the signatures for [partial members](./partial-member.md): +Partial type definitions allow you to split the definition of a class, struct, interface, or record into multiple definitions. You can put these multiple definitions in different files within the same project. One type declaration contains only the signatures for [partial members](./partial-member.md): :::code language="csharp" source="./snippets/PartialMembers.cs" id="DeclaringPart"::: @@ -20,11 +20,13 @@ The other declaration contains the implementation of the partial members: The declarations for a partial type can appear in either the same or multiple files. Typically, the two declarations are in different files. You split a class, struct, or interface type when you're working with large projects, with automatically generated code such as that provided by the [Windows Forms Designer](/dotnet/desktop/winforms/controls/developing-windows-forms-controls-at-design-time), or [Source generators like RegEx](../../../standard/base-types/regular-expression-source-generators.md). A partial type can contain [partial members](partial-member.md). -Beginning with C# 13, you can define partial properties and partial indexers. Beginning with C# 14, you can define partial instance constructors and partial events. Before C# 13, only methods could be defined as partial members. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -Documentation comments can be provided on either the declaring declaration or the implementing declaration. When documentation comments are applied to both type declarations, the XML elements from each declaration are included in the output XML. See the article on [partial members](./partial-member.md) for the rules on partial member declarations. +Starting with C# 13, you can define partial properties and partial indexers. Starting with C# 14, you can define partial instance constructors and partial events. Before C# 13, only methods could be defined as partial members. -You can apply attributes to either declaration. All attributes are both declarations, including duplicates, are combined in the compiled output. +You can provide documentation comments on either the declaring declaration or the implementing declaration. When you apply documentation comments to both type declarations, the XML elements from each declaration are included in the output XML. For the rules on partial member declarations, see the article on [partial members](./partial-member.md). + +You can apply attributes to either declaration. The compiler combines all attributes from both declarations, including duplicates. For more information, see [Partial Classes and Methods](../../programming-guide/classes-and-structs/partial-classes-and-methods.md). diff --git a/docs/csharp/language-reference/keywords/private-protected.md b/docs/csharp/language-reference/keywords/private-protected.md index afd1462f87ff9..b09e4ac2dd312 100644 --- a/docs/csharp/language-reference/keywords/private-protected.md +++ b/docs/csharp/language-reference/keywords/private-protected.md @@ -1,21 +1,18 @@ --- description: "private protected - C# Reference" title: "private protected keyword" -ms.date: 11/15/2017 +ms.date: 01/22/2026 f1_keywords: - "privateprotected_CSharpKeyword" author: "sputier" --- # private protected (C# Reference) -The `private protected` keyword combination is a member access modifier. A private protected member is accessible by types derived from the containing class, but only within its containing assembly. For a comparison of `private protected` with the other access modifiers, see [Accessibility Levels](accessibility-levels.md). +The `private protected` keyword combination is a member access modifier. Types that derive from the class and are declared in the containing assembly can access a private protected member. For a comparison of `private protected` with the other access modifiers, see [Accessibility Levels](accessibility-levels.md). -> [!NOTE] -> The `private protected` access modifier is valid in C# version 7.2 and later. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -## Example - -A private protected member of a base class is accessible from derived types in its containing assembly only if the static type of the variable is the derived class type. For example, consider the following code segment: +Derived types can access a private protected member of a base class in its containing assembly only if the static type of the variable is the derived class type. For example, consider the following code segment: ```csharp // Assembly1.cs @@ -58,9 +55,9 @@ class DerivedClass2 : BaseClass This example contains two files, `Assembly1.cs` and `Assembly2.cs`. The first file contains a public base class, `BaseClass`, and a type derived from it, `DerivedClass1`. `BaseClass` owns a private protected member, `myValue`, which `DerivedClass1` can access as an inherited member within the same assembly. -In the second file, an attempt to access `myValue` as an inherited member of `DerivedClass2` will produce an error, because `private protected` members are only accessible by derived types **within the same assembly**. This is the key difference from `protected` (which allows access from derived classes in any assembly) and `protected internal` (which allows access from any class within the same assembly or derived classes in any assembly). +In the second file, an attempt to access `myValue` as an inherited member of `DerivedClass2` produces an error, because `private protected` members are only accessible by derived types **within the same assembly**. This restriction is the key difference from `protected` (which allows access from derived classes in any assembly) and `protected internal` (which allows access from any class within the same assembly or derived classes in any assembly). -If `Assembly1.cs` contains an that names `Assembly2`, the derived class `DerivedClass2` will have access to `private protected` members declared in `BaseClass`. `InternalsVisibleTo` makes `private protected` members visible to derived classes in other assemblies. +If `Assembly1.cs` contains an that names `Assembly2`, the derived class `DerivedClass2` has access to `private protected` members declared in `BaseClass`. `InternalsVisibleTo` makes `private protected` members visible to derived classes in other assemblies. ## Comparison with other protected access modifiers @@ -72,11 +69,11 @@ The following table summarizes the key differences between the three protected a | `protected internal` | ✔️ | ✔️ | ✔️ | | `private protected` | ✔️ | ❌ | ❌ | -- Use `protected` when you want derived classes in any assembly to access the member -- Use `protected internal` when you want the most permissive access (any class in same assembly OR derived classes anywhere) -- Use `private protected` when you want the most restrictive protected access (only derived classes in the same assembly) +- Use `protected` when you want derived classes in any assembly to access the member. +- Use `protected internal` when you want the most permissive access (any class in the same assembly or derived classes anywhere). +- Use `private protected` when you want the most restrictive protected access (only derived classes in the same assembly). -Struct members cannot be `private protected` because the struct cannot be inherited. +You can't declare `private protected` struct members because structs can't be inherited. ## C# language specification diff --git a/docs/csharp/language-reference/keywords/private.md b/docs/csharp/language-reference/keywords/private.md index e40ea16abafb0..fd651a59b18a6 100644 --- a/docs/csharp/language-reference/keywords/private.md +++ b/docs/csharp/language-reference/keywords/private.md @@ -1,21 +1,22 @@ --- description: "private keyword - C# Reference" title: "private keyword" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "private_CSharpKeyword" - "private" helpviewer_keywords: - "private keyword [C#]" -ms.assetid: 654c0bb8-e6ac-4086-bf96-7474fa6aa1c8 --- # private (C# Reference) The `private` keyword is a member access modifier. -> This page covers `private` access. The `private` keyword is also part of the [`private protected`](./private-protected.md) access modifier. +> This article covers `private` access. The `private` keyword is also part of the [`private protected`](./private-protected.md) access modifier. -Private access is the least permissive access level. Private members are accessible only within the body of the class or the struct in which they are declared, as in this example: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +Private access is the least permissive access level. You can access private members only within the body of the class or the struct where you declare them, as shown in the following example: ```csharp class Employee @@ -27,15 +28,13 @@ class Employee Nested types in the same body can also access those private members. -It is a compile-time error to reference a private member outside the class or the struct in which it is declared. +If you reference a private member outside the class or the struct where you declare it, the compiler returns an error. For a comparison of `private` with the other access modifiers, see [Accessibility Levels](accessibility-levels.md) and [Access Modifiers](../../programming-guide/classes-and-structs/access-modifiers.md). -## Example - -In this example, the `Employee` class contains two private data members, `_name` and `_salary`. As private members, they cannot be accessed except by member methods. Public methods named `GetName` and `Salary` are added to allow controlled access to the private members. The `_name` member is accessed by way of a public method, and the `_salary` member is accessed by way of a public read-only property. For more information, see [Properties](../../programming-guide/classes-and-structs/properties.md). +In this example, the `Employee` class contains two private data members, `_name` and `_salary`. As private members, member methods are the only way to access them. The example adds public methods named `GetName` and `Salary` to allow controlled access to the private members. The `_name` member is accessed by way of a public method, and the `_salary` member is accessed by way of a public read-only property. For more information, see [Properties](../../programming-guide/classes-and-structs/properties.md). -[!code-csharp[csrefKeywordsModifiers#10](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#10)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="10"::: ## C# language specification diff --git a/docs/csharp/language-reference/keywords/protected-internal.md b/docs/csharp/language-reference/keywords/protected-internal.md index 9dae3cdc32e6a..9ab304f20011c 100644 --- a/docs/csharp/language-reference/keywords/protected-internal.md +++ b/docs/csharp/language-reference/keywords/protected-internal.md @@ -1,18 +1,18 @@ --- description: "protected internal - C# Reference" title: "protected internal keyword" -ms.date: 11/15/2017 +ms.date: 01/22/2026 f1_keywords: - "protectedinternal_CSharpKeyword" author: "sputier" --- -# protected internal (C# Reference) +# protected internal (C# reference) -The `protected internal` keyword combination is a member access modifier. A protected internal member is accessible from the current assembly or from types that are derived from the containing class. For a comparison of `protected internal` with the other access modifiers, see [Accessibility Levels](accessibility-levels.md). +The `protected internal` keyword combination is a member access modifier. You can access a protected internal member from the current assembly or from types that are derived from the containing class. For a comparison of `protected internal` with the other access modifiers, see [Accessibility Levels](accessibility-levels.md). -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -A protected internal member of a base class is accessible from any type within its containing assembly. It is also accessible in a derived class located in another assembly only if the access occurs through a variable of the derived class type. For example, consider the following code segment: +Any type within the containing assembly can access a protected internal member of a base class. A derived class located in another assembly can access the member only if the access occurs through a variable of the derived class type. For example, consider the following code segment: ```csharp // Assembly1.cs @@ -53,16 +53,16 @@ class DerivedClass : BaseClass ``` This example contains two files, `Assembly1.cs` and `Assembly2.cs`. -The first file contains a public base class, `BaseClass`, and another class, `TestAccess`. `BaseClass` owns a protected internal member, `myValue`, which is accessed by the `TestAccess` type because they're in the same assembly. -In the second file, an attempt to access `myValue` through an instance of `BaseClass` will produce an error, while an access to this member through an instance of a derived class, `DerivedClass` will succeed. This shows that `protected internal` allows access from **any class within the same assembly** or **derived classes in any assembly**, making it the most permissive of the protected access modifiers. +The first file contains a public base class, `BaseClass`, and another class, `TestAccess`. `BaseClass` owns a protected internal member, `myValue`, which the `TestAccess` type accesses because they're in the same assembly. +In the second file, an attempt to access `myValue` through an instance of `BaseClass` produces an error, while an access to this member through an instance of a derived class, `DerivedClass` succeeds. This access rule shows that `protected internal` allows access from **any class within the same assembly** or **derived classes in any assembly**, making it the most permissive of the protected access modifiers. -Struct members cannot be `protected internal` because the struct cannot be inherited. +Struct members can't be `protected internal` because the struct can't be inherited. ## Overriding protected internal members -When overriding a virtual member, the accessibility modifier of the overridden method depends on the assembly where the derived class is defined. +When you override a virtual member, the accessibility modifier of the overridden method depends on the assembly where you define the derived class. -When the derived class is defined in the same assembly as the base class, all overridden members have `protected internal` access. If the derived class is defined in a different assembly from the base class, overridden members have `protected` access. +When you define the derived class in the same assembly as the base class, all overridden members have `protected internal` access. If you define the derived class in a different assembly from the base class, overridden members have `protected` access. ```csharp // Assembly1.cs diff --git a/docs/csharp/language-reference/keywords/protected.md b/docs/csharp/language-reference/keywords/protected.md index df8f11a27c708..3b095fcbdc623 100644 --- a/docs/csharp/language-reference/keywords/protected.md +++ b/docs/csharp/language-reference/keywords/protected.md @@ -1,51 +1,46 @@ --- description: "protected keyword - C# Reference" title: "protected keyword" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "protected" - "protected_CSharpKeyword" helpviewer_keywords: - "protected keyword [C#]" -ms.assetid: 05ce3794-6675-4025-bddb-eaaa0ec22892 --- # protected (C# Reference) The `protected` keyword is a member access modifier. > [!NOTE] -> This page covers `protected` access. The `protected` keyword is also part of the [`protected internal`](protected-internal.md) and [`private protected`](private-protected.md) access modifiers. +> This article covers `protected` access. The `protected` keyword is also part of the [`protected internal`](protected-internal.md) and [`private protected`](private-protected.md) access modifiers. -A protected member is accessible within its class and by derived class instances. +You can access a protected member within its class and by derived class instances. For a comparison of `protected` with the other access modifiers, see [Accessibility Levels](accessibility-levels.md). -## Example 1 +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -A protected member of a base class is accessible in a derived class only if the access occurs through the derived class type. For example, consider the following code segment: +You can access a protected member of a base class in a derived class only if the access occurs through the derived class type. For example, consider the following code segment: :::code language="csharp" source="./snippets/protected/Example1.cs" id="snippet1"::: -The statement `baseObject.myValue = 10` generates an error because it accesses the protected member through a base class reference (`baseObject` is of type `BaseClass`). Protected members can only be accessed through the derived class type or types derived from it. +The statement `baseObject.myValue = 10` generates an error because it accesses the protected member through a base class reference (`baseObject` is of type `BaseClass`). You can only access protected members through the derived class type or types derived from it. -Unlike `private protected`, the `protected` access modifier allows access from derived classes **in any assembly**. Unlike `protected internal`, it does **not** allow access from non-derived classes within the same assembly. +Unlike `private protected`, the `protected` access modifier allows access from derived classes **in any assembly**. Unlike `protected internal`, it doesn't allow access from non-derived classes within the same assembly. -Struct members cannot be protected because the struct cannot be inherited. - -## Example 2 +You can't declare struct members as protected because structs can't be inherited. In this example, the class `DerivedPoint` is derived from `Point`. Therefore, you can access the protected members of the base class directly from the derived class. :::code language="csharp" source="./snippets/protected/Example2.cs" id="snippet1"::: -If you change the access levels of `x` and `y` to [private](private.md), the compiler will issue the error messages: +If you change the access levels of `x` and `y` to [private](private.md), the compiler returns the error messages: `'Point.y' is inaccessible due to its protection level.` `'Point.x' is inaccessible due to its protection level.` -## Cross-assembly access - The following example demonstrates that `protected` members are accessible from derived classes even when they're in different assemblies: :::code language="csharp" source="./snippets/protected/Assembly1.cs" id="snippet1"::: diff --git a/docs/csharp/language-reference/keywords/public.md b/docs/csharp/language-reference/keywords/public.md index bbe1a3ad4195e..511f002408294 100644 --- a/docs/csharp/language-reference/keywords/public.md +++ b/docs/csharp/language-reference/keywords/public.md @@ -1,17 +1,16 @@ --- description: "public keyword - C# Reference" title: "public keyword" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "public" - "public_CSharpKeyword" helpviewer_keywords: - "public keyword [C#]" -ms.assetid: 0ae45d16-a551-4b74-9845-57208de1328e --- -# public (C# Reference) +# public (C# reference) -The `public` keyword is an access modifier for types and type members. Public access is the most permissive access level. There are no restrictions on accessing public members, as in this example: +Use the `public` keyword as an access modifier for types and type members. Public access is the most permissive access level. The following example shows that you can access public members without any restrictions: ```csharp class SampleClass @@ -20,15 +19,15 @@ class SampleClass } ``` -See [Access Modifiers](../../programming-guide/classes-and-structs/access-modifiers.md) and [Accessibility Levels](accessibility-levels.md) for more information. +For more information, see [Access Modifiers](../../programming-guide/classes-and-structs/access-modifiers.md) and [Accessibility Levels](accessibility-levels.md). -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] In the following example, two classes are declared, `PointTest` and `Program`. The public members `x` and `y` of `PointTest` are accessed directly from `Program`. -[!code-csharp[csrefKeywordsModifiers#13](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#13)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="13"::: -If you change the `public` access level to [private](private.md) or [protected](protected.md), you will get the error message: +If you change the `public` access level to [private](private.md) or [protected](protected.md), you get the error message: 'PointTest.y' is inaccessible due to its protection level. diff --git a/docs/csharp/language-reference/keywords/query-keywords.md b/docs/csharp/language-reference/keywords/query-keywords.md index f3b66b3cac599..61499d1a7338f 100644 --- a/docs/csharp/language-reference/keywords/query-keywords.md +++ b/docs/csharp/language-reference/keywords/query-keywords.md @@ -1,11 +1,10 @@ --- description: "Query keywords - C# Reference" title: "Query keywords" -ms.date: 07/20/2015 +ms.date: 01/22/2026 helpviewer_keywords: - "query keywords [C#]" - "LINQ [C#], query keywords" -ms.assetid: 6c9bec16-dbd7-4a7c-a060-fe4600b2021f --- # Query keywords (C# Reference) @@ -13,22 +12,20 @@ This section contains the contextual keywords used in query expressions. ## In this section -|Clause|Description| -|------------|-----------------| -|[from](from-clause.md)|Specifies a data source and a range variable (similar to an iteration variable).| -|[where](where-clause.md)|Filters source elements based on one or more Boolean expressions separated by logical AND and OR operators ( `&&` or || ).| -|[select](select-clause.md)|Specifies the type and shape that the elements in the returned sequence will have when the query is executed.| -|[group](group-clause.md)|Groups query results according to a specified key value.| -|[into](into.md)|Provides an identifier that can serve as a reference to the results of a join, group or select clause.| -|[orderby](orderby-clause.md)|Sorts query results in ascending or descending order based on the default comparer for the element type.| -|[join](join-clause.md)|Joins two data sources based on an equality comparison between two specified matching criteria.| -|[let](let-clause.md)|Introduces a range variable to store subexpression results in a query expression.| -|[in](in.md)|Contextual keyword in a [join](join-clause.md) clause.| -|[on](on.md)|Contextual keyword in a [join](join-clause.md) clause.| -|[equals](equals.md)|Contextual keyword in a [join](join-clause.md) clause.| -|[by](by.md)|Contextual keyword in a [group](group-clause.md) clause.| -|[ascending](ascending.md)|Contextual keyword in an [orderby](orderby-clause.md) clause.| -|[descending](descending.md)|Contextual keyword in an [orderby](orderby-clause.md) clause.| +- [from](from-clause.md): Specifies a data source and a range variable (similar to an iteration variable). +- [where](where-clause.md): Filters source elements based on one or more Boolean expressions separated by logical AND and OR operators (`&&` or `||`). +- [select](select-clause.md): Specifies the type and shape that the elements in the returned sequence have when the query executes. +- [group](group-clause.md): Groups query results according to a specified key value. +- [into](into.md): Provides an identifier that serves as a reference to the results of a join, group, or select clause. +- [orderby](orderby-clause.md): Sorts query results in ascending or descending order based on the default comparer for the element type. +- [join](join-clause.md): Joins two data sources based on an equality comparison between two specified matching criteria. +- [let](let-clause.md): Introduces a range variable to store subexpression results in a query expression. +- [in](in.md): Contextual keyword in a [join](join-clause.md) clause. +- [on](on.md): Contextual keyword in a [join](join-clause.md) clause. +- [equals](equals.md): Contextual keyword in a [join](join-clause.md) clause. +- [by](by.md): Contextual keyword in a [group](group-clause.md) clause. +- [ascending](ascending.md): Contextual keyword in an [orderby](orderby-clause.md) clause. +- [descending](descending.md): Contextual keyword in an [orderby](orderby-clause.md) clause. ## See also diff --git a/docs/csharp/language-reference/keywords/readonly.md b/docs/csharp/language-reference/keywords/readonly.md index 8272a4b492ab5..26ae2cfe96a47 100644 --- a/docs/csharp/language-reference/keywords/readonly.md +++ b/docs/csharp/language-reference/keywords/readonly.md @@ -1,42 +1,43 @@ --- description: "readonly keyword - C# Reference" title: "readonly keyword" -ms.date: 01/09/2024 +ms.date: 01/22/2026 f1_keywords: - "readonly_CSharpKeyword" - "readonly" helpviewer_keywords: - "readonly keyword [C#]" -ms.assetid: 2f8081f6-0de2-4903-898d-99696c48d2f4 --- -# readonly (C# Reference) +# readonly (C# reference) -The `readonly` keyword is a modifier that can be used in five contexts: +Use the `readonly` keyword as a modifier in five contexts: -- In a [field declaration](#readonly-field-example), `readonly` indicates that assignment to the field can only occur as part of the declaration or in a constructor in the same class. A readonly field can be assigned and reassigned multiple times within the field declaration and constructor. +- In a [field declaration](#readonly-field-example), `readonly` means you can only assign the field during the declaration or in a constructor in the same class. You can assign and reassign a readonly field multiple times within the field declaration and constructor. - A `readonly` field can't be assigned after the constructor exits. This rule has different implications for value types and reference types: + You can't assign a `readonly` field after the constructor finishes. This rule affects value types and reference types differently: - Because value types directly contain their data, a field that is a `readonly` value type is immutable. - Because reference types contain a reference to their data, a field that is a `readonly` reference type must always refer to the same object. That object might not be immutable. The `readonly` modifier prevents replacing the field value with a different instance of the reference type. However, the modifier doesn't prevent the instance data of the field from being modified through the read-only field. > [!WARNING] - > An externally visible type that contains an externally visible read-only field that is a mutable reference type may be a security vulnerability and may trigger warning [CA2104](/visualstudio/code-quality/ca2104) : "Do not declare read only mutable reference types." + > An externally visible type that contains an externally visible read-only field that is a mutable reference type might be a security vulnerability and might trigger warning [CA2104](/visualstudio/code-quality/ca2104) : "Do not declare read only mutable reference types." -- In a `readonly struct` type definition, `readonly` indicates that the structure type is immutable. For more information, see the [`readonly` struct](../builtin-types/struct.md#readonly-struct) section of the [Structure types](../builtin-types/struct.md) article. -- In an instance member declaration within a structure type, `readonly` indicates that an instance member doesn't modify the state of the structure. For more information, see the [`readonly` instance members](../builtin-types/struct.md#readonly-instance-members) section of the [Structure types](../builtin-types/struct.md) article. -- In a [`ref readonly` method return](#ref-readonly-return-example), the `readonly` modifier indicates that method returns a reference and writes aren't allowed to that reference. +- In a `readonly struct` type definition, `readonly` means the structure type is immutable. For more information, see the [`readonly` struct](../builtin-types/struct.md#readonly-struct) section of the [Structure types](../builtin-types/struct.md) article. +- In an instance member declaration within a structure type, `readonly` means an instance member doesn't modify the state of the structure. For more information, see the [`readonly` instance members](../builtin-types/struct.md#readonly-instance-members) section of the [Structure types](../builtin-types/struct.md) article. +- In a [`ref readonly` method return](#ref-readonly-return-example), the `readonly` modifier indicates that the method returns a reference and writes aren't allowed to that reference. - To declare a [`ref readonly` parameter](method-parameters.md#ref-readonly-modifier) to a method. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + ## Readonly field example -In this example, the value of the field `year` can't be changed in the method `ChangeYear`, even though it was assigned a value in the class constructor: +In this example, you can't change the value of the `year` field in the `ChangeYear` method, even though the class constructor assigns a value to it: :::code language="csharp" source="snippets/ReadonlyKeywordExamples.cs" id="ReadonlyField"::: You can assign a value to a `readonly` field only in the following contexts: -- When the variable is initialized in the declaration, for example: +- When you initialize the variable in the declaration, for example: ```csharp public readonly int y = 5; @@ -48,7 +49,7 @@ You can assign a value to a `readonly` field only in the following contexts: These constructor contexts are also the only contexts in which it's valid to pass a `readonly` field as an [out](method-parameters.md#out-parameter-modifier) or [ref](ref.md) parameter. > [!NOTE] -> The `readonly` keyword is different from the [const](const.md) keyword. A `const` field can only be initialized at the declaration of the field. A `readonly` field can be assigned multiple times in the field declaration and in any constructor. Therefore, `readonly` fields can have different values depending on the constructor used. Also, while a `const` field is a compile-time constant, the `readonly` field can be used for run-time constants as in the following example: +> The `readonly` keyword is different from the [const](const.md) keyword. You can only initialize a `const` field at the declaration of the field. You can assign a `readonly` field multiple times in the field declaration and in any constructor. Therefore, `readonly` fields can have different values depending on the constructor used. Also, while a `const` field is a compile-time constant, the `readonly` field can be used for run-time constants as in the following example: > > ```csharp > public static readonly uint timeStamp = (uint)DateTime.Now.Ticks; @@ -68,26 +69,26 @@ you get the compiler error message: ## Readonly instance members -You can also use the `readonly` modifier to declare that an instance member doesn't modify the state of a struct. +Use the `readonly` modifier to declare that an instance member doesn't modify the state of a struct. :::code language="csharp" source="../builtin-types/snippets/shared/StructType.cs" id="SnippetReadonlyMethod"::: > [!NOTE] -> In the case of a read/write property, you can add the `readonly` modifier to the `get` accessor. Some `get` accessors may perform a calculation and cache the result, rather than simply returning the value of a private field. Adding the `readonly` modifier to the `get` accessor guarantees that the `get` accessor doesn't modify the internal state of the object by caching any result. +> For a read/write property, you can add the `readonly` modifier to the `get` accessor. Some `get` accessors perform a calculation and cache the result, rather than simply returning the value of a private field. By adding the `readonly` modifier to the `get` accessor, you guarantee that the `get` accessor doesn't modify the internal state of the object by caching any result. -You can find more examples in the [`readonly` instance members](../builtin-types/struct.md#readonly-instance-members) section of the [Structure types](../builtin-types/struct.md) article. +For more examples, see the [`readonly` instance members](../builtin-types/struct.md#readonly-instance-members) section of the [Structure types](../builtin-types/struct.md) article. ## Ref readonly return example -The `readonly` modifier on a `ref return` indicates that the returned reference can't be modified. The following example returns a reference to the origin. It uses the `readonly` modifier to indicate that callers can't modify the origin: +A `readonly` modifier on a `ref return` indicates that the returned reference can't be modified. The following example returns a reference to the origin. It uses the `readonly` modifier to indicate that callers can't modify the origin: :::code language="csharp" source="snippets/ReadonlyKeywordExamples.cs" id="ReadonlyReturn"::: -The type returned doesn't need to be a `readonly struct`. Any type that can be returned by `ref` can be returned by `ref readonly`. +The type returned doesn't need to be a `readonly struct`. Any type that `ref` can return can also be returned by `ref readonly`. ## Readonly ref readonly return example -A `ref readonly return` can also be used with `readonly` instance members on `struct` types: +You can also use a `ref readonly return` with `readonly` instance members on `struct` types: :::code language="csharp" source="./snippets/ReadonlyKeywordExamples.cs" id="SnippetReadonlyRefReadonly"::: diff --git a/docs/csharp/language-reference/keywords/ref.md b/docs/csharp/language-reference/keywords/ref.md index 62583be2a44ce..84bc4195b74f7 100644 --- a/docs/csharp/language-reference/keywords/ref.md +++ b/docs/csharp/language-reference/keywords/ref.md @@ -1,7 +1,7 @@ --- description: "Understand the different uses for the `ref` keyword and get more information on those uses" title: "The multiple uses of the `ref` keyword" -ms.date: 09/23/2023 +ms.date: 01/22/2026 f1_keywords: - "ref_CSharpKeyword" helpviewer_keywords: @@ -13,29 +13,16 @@ helpviewer_keywords: You use the `ref` keyword in the following contexts: - In a method signature and in a method call, to pass an argument to a method [by reference](./method-parameters.md#ref-parameter-modifier). - -:::code language="csharp" source="./snippets/refKeyword.cs" id="PassByReference"::: - + :::code language="csharp" source="./snippets/refKeyword.cs" id="PassByReference"::: - In a method signature, to return a value to the caller by reference. For more information, see [`ref return`](../statements/jump-statements.md#ref-returns). - -:::code language="csharp" source="./snippets/refKeyword.cs" id="ReturnByReference"::: - + :::code language="csharp" source="./snippets/refKeyword.cs" id="ReturnByReference"::: - In a declaration of a local variable, to declare a [reference variable](../statements/declarations.md#reference-variables). - -:::code language="csharp" source="./snippets/refKeyword.cs" id="LocalRef"::: - + :::code language="csharp" source="./snippets/refKeyword.cs" id="LocalRef"::: - As the part of a [conditional ref expression](../operators/conditional-operator.md#conditional-ref-expression) or a [ref assignment operator](../operators/assignment-operator.md#ref-assignment). - -:::code language="csharp" source="./snippets/refKeyword.cs" id="ConditionalRef"::: - + :::code language="csharp" source="./snippets/refKeyword.cs" id="ConditionalRef"::: - In a `struct` declaration, to declare a `ref struct`. For more information, see the [`ref` structure types](../builtin-types/ref-struct.md) article. - -:::code language="csharp" source="./snippets/refKeyword.cs" id="SnippetRefStruct"::: - + :::code language="csharp" source="./snippets/refKeyword.cs" id="SnippetRefStruct"::: - In a `ref struct` definition, to declare a `ref` field. For more information, see the [`ref` fields](../builtin-types/ref-struct.md#ref-fields) section of the [`ref` structure types](../builtin-types/ref-struct.md) article. - -:::code language="csharp" source="./snippets/refKeyword.cs" id="SnippetRefField"::: - + :::code language="csharp" source="./snippets/refKeyword.cs" id="SnippetRefField"::: - In a generic type declaration to specify that a type parameter [`allows ref struct`](../../programming-guide/generics/constraints-on-type-parameters.md#allows-ref-struct) types. - -:::code language="csharp" source="./snippets/refKeyword.cs" id="SnippetRefGeneric"::: + :::code language="csharp" source="./snippets/refKeyword.cs" id="SnippetRefGeneric"::: diff --git a/docs/csharp/language-reference/keywords/reference-types.md b/docs/csharp/language-reference/keywords/reference-types.md index 8a69674005a62..f0121a0552b98 100644 --- a/docs/csharp/language-reference/keywords/reference-types.md +++ b/docs/csharp/language-reference/keywords/reference-types.md @@ -1,20 +1,21 @@ --- description: "Reference types - C# Reference" title: "Reference types" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "cs.referencetypes" helpviewer_keywords: - "reference types [C#]" - "C# language, reference types" - "types [C#], reference types" -ms.assetid: 801cf030-6e2d-4a0d-9daf-1431b0c31f47 --- # Reference types (C# reference) -There are two kinds of types in C#: reference types and value types. Variables of reference types store references to their data (objects), while variables of value types directly contain their data. With reference types, two variables can reference the same object; therefore, operations on one variable can affect the object referenced by the other variable. With value types, each variable has its own copy of the data, and it's not possible for operations on one variable to affect the other (except in the case of `in`, `ref`, and `out` parameter variables; see [in](method-parameters.md#in-parameter-modifier), [ref](ref.md), and [out](method-parameters.md#out-parameter-modifier) parameter modifier). +C# has two kinds of types: reference types and value types. Variables of reference types store references to their data (objects), while variables of value types directly contain their data. With reference types, two variables can reference the same object. Therefore, operations on one variable can affect the object referenced by the other variable. With value types, each variable has its own copy of the data. Operations on one variable can't affect the other variable, except in the case of `in`, `ref`, and `out` parameter variables. For more information, see [in](method-parameters.md#in-parameter-modifier), [ref](ref.md), and [out](method-parameters.md#out-parameter-modifier) parameter modifier. - The following keywords are used to declare reference types: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + + Use the following keywords to declare reference types: - [class](class.md) - [interface](interface.md) diff --git a/docs/csharp/language-reference/keywords/remove.md b/docs/csharp/language-reference/keywords/remove.md index b432d7f8b142d..8d58270c69b0d 100644 --- a/docs/csharp/language-reference/keywords/remove.md +++ b/docs/csharp/language-reference/keywords/remove.md @@ -1,7 +1,7 @@ --- description: "The `remove` contextual keyword declares an event accessor that removes a handler from that event. - C# Reference" title: "The `remove` contextual keyword" -ms.date: 03/13/2025 +ms.date: 01/22/2026 f1_keywords: - "remove_CSharpKeyword" helpviewer_keywords: @@ -9,13 +9,15 @@ helpviewer_keywords: --- # The `remove` contextual keyword (C# Reference) -The `remove` contextual keyword is used to define a custom event accessor that is invoked when client code unsubscribes from your [event](event.md). If you supply a custom `remove` accessor, you must also supply an [add](add.md) accessor. +Use the `remove` contextual keyword to define a custom event accessor that's invoked when client code unsubscribes from your [event](event.md). If you supply a custom `remove` accessor, you must also supply an [add](add.md) accessor. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] The following example shows an event with custom [add](add.md) and `remove` accessors. For the full example, see [How to implement interface events](../../programming-guide/events/how-to-implement-interface-events.md). :::code language="csharp" source="./snippets/events.cs" id="AddHandler"::: -You don't typically need to provide your own custom event accessors. The automatically generated accessors when you declare an event are sufficient for most scenarios. Beginning with C# 14, you can declare [`partial`](./partial-member.md) events. The implementing declaration of a partial event must declare the `add` and `remove` handlers. +You don't typically need to provide your own custom event accessors. The automatically generated accessors when you declare an event are sufficient for most scenarios. Starting with C# 14, you can declare [`partial`](./partial-member.md) events. The implementing declaration of a partial event must declare the `add` and `remove` handlers. ## See also diff --git a/docs/csharp/language-reference/keywords/required.md b/docs/csharp/language-reference/keywords/required.md index 105465d33bdea..8afa29034d96a 100644 --- a/docs/csharp/language-reference/keywords/required.md +++ b/docs/csharp/language-reference/keywords/required.md @@ -1,7 +1,7 @@ --- description: "required modifier - C# Reference" title: "required modifier" -ms.date: 01/30/2023 +ms.date: 01/22/2026 f1_keywords: - "required_CSharpKeyword" helpviewer_keywords: @@ -9,23 +9,27 @@ helpviewer_keywords: --- # required modifier (C# Reference) -The `required` modifier indicates that the *field* or *property* it's applied to must be initialized by an [object initializer](../../programming-guide/classes-and-structs/object-and-collection-initializers.md). Any expression that initializes a new instance of the type must initialize all *required members*. The `required` modifier is available beginning with C# 11. The `required` modifier enables developers to create types where properties or fields must be properly initialized, yet still allow initialization using object initializers. Several rules ensure this behavior: +The `required` modifier indicates that the *field* or *property* it applies to must be initialized by an [object initializer](../../programming-guide/classes-and-structs/object-and-collection-initializers.md). Any expression that initializes a new instance of the type must initialize all *required members*. The `required` modifier is available starting with C# 11. -- The `required` modifier can be applied to *fields* and *properties* declared in `struct`, and `class` types, including `record` and `record struct` types. The `required` modifier can't be applied to members of an `interface`. -- Explicit interface implementations can't be marked as `required`. They can't be set in object initializers. -- Required members must be initialized, but they may be initialized to `null`. If the type is a non-nullable reference type, the compiler issues a warning if you initialize the member to `null`. The compiler issues an error if the member isn't initialized at all. -- Required members must be at least as visible as their containing type. For example, a `public` class can't contain a `required` field that's `protected`. Furthermore, required properties must have setters (`set` or `init` accessors) that are at least as visible as their containing types. Members that aren't accessible can't be set by code that creates an instance. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +By using the `required` modifier, developers can create types where properties or fields must be properly initialized, yet still allow initialization through object initializers. Several rules ensure this behavior: + +- Apply the `required` modifier to *fields* and *properties* declared in `struct` and `class` types, including `record` and `record struct` types. You can't apply the `required` modifier to members of an `interface`. +- You can't mark explicit interface implementations as `required`. You can't set them in object initializers. +- You must initialize required members, but you can initialize them to `null`. If the type is a non-nullable reference type, the compiler issues a warning if you initialize the member to `null`. The compiler issues an error if the member isn't initialized at all. +- Required members must be at least as visible as their containing type. For example, a `public` class can't contain a `required` field that's `protected`. Furthermore, required properties must have setters (`set` or `init` accessors) that are at least as visible as their containing types. Code that creates an instance can't set members that aren't accessible. - Derived classes can't hide a `required` member declared in the base class. Hiding a required member prevents callers from using object initializers for it. Furthermore, derived types that override a required property must include the `required` modifier. The derived type can't remove the `required` state. Derived types can add the `required` modifier when overriding a property. -- A type with any `required` members may not be used as a type argument when the type parameter includes the `new()` constraint. The compiler can't enforce that all required members are initialized in the generic code. -- The `required` modifier isn't allowed on the declaration for positional parameters on a record. You can add an explicit declaration for a positional property that does include the `required` modifier. +- You can't use a type with any `required` members as a type argument when the type parameter includes the `new()` constraint. The compiler can't enforce that all required members are initialized in the generic code. +- You can't use the `required` modifier on the declaration for positional parameters on a record. You can add an explicit declaration for a positional property that does include the `required` modifier. -Some types, such as [positional records](../builtin-types/record.md#positional-syntax-for-property-and-field-definition), use a primary constructor to initialize positional properties. If any of those properties include the `required` modifier, the primary constructor adds the [`SetsRequiredMembers`](../attributes/general.md#setsrequiredmembers-attribute) attribute. This indicates that the primary constructor initializes all required members. You can write your own constructor with the attribute. However, the compiler doesn't verify that these constructors do initialize all required members. Rather, the attribute asserts to the compiler that the constructor does initialize all required members. The `SetsRequiredMembers` attribute adds these rules to constructors: +Some types, such as [positional records](../builtin-types/record.md#positional-syntax-for-property-and-field-definition), use a primary constructor to initialize positional properties. If any of those properties include the `required` modifier, the primary constructor adds the [`SetsRequiredMembers`](../attributes/general.md#setsrequiredmembers-attribute) attribute. This attribute indicates that the primary constructor initializes all required members. You can write your own constructor with the attribute. However, the compiler doesn't verify that these constructors do initialize all required members. Rather, the attribute asserts to the compiler that the constructor does initialize all required members. The `SetsRequiredMembers` attribute adds these rules to constructors: - A constructor that chains to another constructor annotated with the `SetsRequiredMembers` attribute, either `this()`, or `base()`, must also include the `SetsRequiredMembers` attribute. That ensures that callers can correctly use all appropriate constructors. - Copy constructors generated for `record` types have the `SetsRequiredMembers` attribute applied if any of the members are `required`. > [!WARNING] -> The `SetsRequiredMembers` disables the compiler's checks that all `required` members are initialized when an object is created. Use it with caution. +> The `SetsRequiredMembers` attribute disables the compiler's checks that all `required` members are initialized when an object is created. Use it with caution. The following code shows a class hierarchy that uses the `required` modifier for the `FirstName` and `LastName` properties: diff --git a/docs/csharp/language-reference/keywords/restrictions-on-using-accessibility-levels.md b/docs/csharp/language-reference/keywords/restrictions-on-using-accessibility-levels.md index 104c0c092929d..036f031b96912 100644 --- a/docs/csharp/language-reference/keywords/restrictions-on-using-accessibility-levels.md +++ b/docs/csharp/language-reference/keywords/restrictions-on-using-accessibility-levels.md @@ -1,37 +1,34 @@ --- description: "Restrictions on using accessibility levels - C# Reference" title: "Restrictions on using accessibility levels" -ms.date: 07/20/2015 +ms.date: 01/22/2026 helpviewer_keywords: - "access modifiers [C#], accessibility level restrictions" -ms.assetid: 987e2f22-46bf-4fea-80ee-270b9cd01045 --- # Restrictions on using accessibility levels (C# Reference) -When you specify a type in a declaration, check whether the accessibility level of the type is dependent on the accessibility level of a member or of another type. For example, the direct base class must be at least as accessible as the derived class. The following declarations cause a compiler error because the base class `BaseClass` is less accessible than `MyClass`: +When you specify a type in a declaration, check whether the accessibility level of the type depends on the accessibility level of a member or another type. For example, the direct base class must be at least as accessible as the derived class. The following declarations cause a compiler error because the base class `BaseClass` is less accessible than `MyClass`: ```csharp class BaseClass {...} public class MyClass: BaseClass {...} // Error ``` -The following table summarizes the restrictions on declared accessibility levels. - -|Context|Remarks| -|-------------|-------------| -|[Classes](../../fundamentals/types/classes.md)|The direct base class of a class type must be at least as accessible as the class type itself.| -|[Interfaces](../../fundamentals/types/interfaces.md)|The explicit base interfaces of an interface type must be at least as accessible as the interface type itself.| -|[Delegates](../../programming-guide/delegates/index.md)|The return type and parameter types of a delegate type must be at least as accessible as the delegate type itself.| -|[Constants](../../programming-guide/classes-and-structs/constants.md)|The type of a constant must be at least as accessible as the constant itself.| -|[Fields](../../programming-guide/classes-and-structs/fields.md)|The type of a field must be at least as accessible as the field itself.| -|[Methods](../../programming-guide/classes-and-structs/methods.md)|The return type and parameter types of a method must be at least as accessible as the method itself.| -|[Properties](../../programming-guide/classes-and-structs/properties.md)|The type of a property must be at least as accessible as the property itself.| -|[Events](../../programming-guide/events/index.md)|The type of an event must be at least as accessible as the event itself.| -|[Indexers](../../programming-guide/indexers/index.md)|The type and parameter types of an indexer must be at least as accessible as the indexer itself.| -|[Operators](../operators/index.md)|The return type and parameter types of an operator must be at least as accessible as the operator itself.| -|[Constructors](../../programming-guide/classes-and-structs/constructors.md)|The parameter types of a constructor must be at least as accessible as the constructor itself.| - -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +The following list summarizes the restrictions on declared accessibility levels. + +- [Classes](../../fundamentals/types/classes.md): The direct base class of a class type must be at least as accessible as the class type itself. +- [Interfaces](../../fundamentals/types/interfaces.md): The explicit base interfaces of an interface type must be at least as accessible as the interface type itself. +- [Delegates](../../programming-guide/delegates/index.md): The return type and parameter types of a delegate type must be at least as accessible as the delegate type itself. +- [Constants](../../programming-guide/classes-and-structs/constants.md): The type of a constant must be at least as accessible as the constant itself. +- [Fields](../../programming-guide/classes-and-structs/fields.md): The type of a field must be at least as accessible as the field itself. +- [Methods](../../programming-guide/classes-and-structs/methods.md): The return type and parameter types of a method must be at least as accessible as the method itself. +- [Properties](../../programming-guide/classes-and-structs/properties.md): The type of a property must be at least as accessible as the property itself. +- [Events](../../programming-guide/events/index.md): The type of an event must be at least as accessible as the event itself. +- [Indexers](../../programming-guide/indexers/index.md): The type and parameter types of an indexer must be at least as accessible as the indexer itself. +- [Operators](../operators/index.md): The return type and parameter types of an operator must be at least as accessible as the operator itself. +- [Constructors](../../programming-guide/classes-and-structs/constructors.md): The parameter types of a constructor must be at least as accessible as the constructor itself. The following example contains erroneous declarations of different types. The comment following each declaration indicates the expected compiler error. diff --git a/docs/csharp/language-reference/keywords/sealed.md b/docs/csharp/language-reference/keywords/sealed.md index 1f6aa24ef27cd..9220e2e3c8394 100644 --- a/docs/csharp/language-reference/keywords/sealed.md +++ b/docs/csharp/language-reference/keywords/sealed.md @@ -1,49 +1,48 @@ --- description: "sealed modifier - C# Reference" title: "sealed modifier" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "sealed" - "sealed_CSharpKeyword" helpviewer_keywords: - "sealed keyword [C#]" -ms.assetid: 8e4ed5d3-10be-47db-9488-0da2008e6f3f --- # sealed (C# Reference) -When applied to a class, the `sealed` modifier prevents other classes from inheriting from it. In the following example, class `B` inherits from class `A`, but no class can inherit from class `B`. +When you apply the `sealed` modifier to a class, it prevents other classes from inheriting from that class. In the following example, class `B` inherits from class `A`, but no class can inherit from class `B`. ```csharp class A {} sealed class B : A {} ``` -You can also use the `sealed` modifier on a method or property that overrides a virtual method or property in a base class. This enables you to allow classes to derive from your class and prevent them from overriding specific virtual methods or properties. +You can also use the `sealed` modifier on a method or property that overrides a virtual method or property in a base class. By using this approach, you enable developers to derive classes from your class while preventing them from overriding specific virtual methods or properties. -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -In the following example, `Z` inherits from `Y` but `Z` cannot override the virtual function `F` that is declared in `X` and sealed in `Y`. +In the following example, `Z` inherits from `Y` but `Z` can't override the virtual function `F` that is declared in `X` and sealed in `Y`. -[!code-csharp[csrefKeywordsModifiers#16](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#16)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="16"::: When you define new methods or properties in a class, you can prevent deriving classes from overriding them by not declaring them as [virtual](virtual.md). -When you override a `virtual` member declared in a base type, you can prevent deriving types from overriding them by using sealed keyword as in the following example: +When you override a `virtual` member declared in a base type, you can prevent deriving types from overriding it by using the `sealed` keyword as shown in the following example: ``` public sealed override string ToString() => Value; ``` -It is an error to use the [abstract](abstract.md) modifier with a sealed class, because an abstract class must be inherited by a class that provides an implementation of the abstract methods or properties. +It's an error to use the [abstract](abstract.md) modifier with a sealed class, because an abstract class must be inherited by a class that provides an implementation of the abstract methods or properties. -When applied to a method or property, the `sealed` modifier must always be used with [override](override.md). +When you apply the `sealed` modifier to a method or property, always use it with [override](override.md). -Because structs are implicitly sealed, they cannot be inherited. +Because structs are implicitly sealed, you can't inherit from them. For more information, see [Inheritance](../../fundamentals/object-oriented/inheritance.md). For more examples, see [Abstract and Sealed Classes and Class Members](../../programming-guide/classes-and-structs/abstract-and-sealed-classes-and-class-members.md). -[!code-csharp[csrefKeywordsModifiers#17](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#17)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="17"::: In the previous example, you might try to inherit from the sealed class by using the following statement: @@ -53,13 +52,10 @@ The result is an error message: `'MyDerivedC': cannot derive from sealed type 'SealedClass'` -## Remarks - -To determine whether to seal a class, method, or property, you should generally consider the following two points: +To determine whether to seal a class, method, or property, generally consider the following two points: - The potential benefits that deriving classes might gain through the ability to customize your class. - -- The potential that deriving classes could modify your classes in such a way that they would no longer work correctly or as expected. +- The potential that deriving classes could modify your classes in such a way that they no longer work correctly or as expected. ## C# language specification diff --git a/docs/csharp/language-reference/keywords/select-clause.md b/docs/csharp/language-reference/keywords/select-clause.md index f2e9eb0bfb001..2cbdfeb46830d 100644 --- a/docs/csharp/language-reference/keywords/select-clause.md +++ b/docs/csharp/language-reference/keywords/select-clause.md @@ -1,34 +1,31 @@ --- description: "select clause - C# Reference" title: "select clause" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "select_CSharpKeyword" - "select" helpviewer_keywords: - "select keyword [C#]" - "select clause [C#]" -ms.assetid: df01e266-5781-4aaa-80c4-67cf28ea093f --- # select clause (C# Reference) -In a query expression, the `select` clause specifies the type of values that will be produced when the query is executed. The result is based on the evaluation of all the previous clauses and on any expressions in the `select` clause itself. A query expression must terminate with either a `select` clause or a [group](group-clause.md) clause. +In a query expression, the `select` clause specifies the type of values that the query produces when it runs. The result comes from evaluating all the previous clauses and any expressions in the `select` clause itself. A query expression must end with either a `select` clause or a [group](group-clause.md) clause. The following example shows a simple `select` clause in a query expression. -[!code-csharp[cscsrefQueryKeywords#8](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Select.cs#8)] +:::code language="csharp" source="./snippets/select.cs" id="8"::: -The type of the sequence produced by the `select` clause determines the type of the query variable `queryHighScores`. In the simplest case, the `select` clause just specifies the range variable. This causes the returned sequence to contain elements of the same type as the data source. For more information, see [Type Relationships in LINQ Query Operations](../../linq/get-started/type-relationships-in-linq-query-operations.md). However, the `select` clause also provides a powerful mechanism for transforming (or *projecting*) source data into new types. For more information, see [Data Transformations with LINQ (C#)](../../linq/standard-query-operators/index.md). +The type of the sequence that the `select` clause produces determines the type of the query variable `queryHighScores`. In the simplest case, the `select` clause just specifies the range variable. This approach makes the returned sequence contain elements of the same type as the data source. For more information, see [Type Relationships in LINQ Query Operations](../../linq/get-started/type-relationships-in-linq-query-operations.md). However, the `select` clause also provides a powerful mechanism for transforming (or *projecting*) source data into new types. For more information, see [Data Transformations with LINQ (C#)](../../linq/standard-query-operators/index.md). -## Example +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -The following example shows all the different forms that a `select` clause may take. In each query, note the relationship between the `select` clause and the type of the *query variable* (`studentQuery1`, `studentQuery2`, and so on). +The following example shows all the different forms that a `select` clause can take. In each query, note the relationship between the `select` clause and the type of the *query variable* (`studentQuery1`, `studentQuery2`, and so on). -[!code-csharp[cscsrefQueryKeywords#9](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Select.cs#9)] +:::code language="csharp" source="./snippets/select.cs" id="9"::: -As shown in `studentQuery8` in the previous example, sometimes you might want the elements of the returned sequence to contain only a subset of the properties of the source elements. By keeping the returned sequence as small as possible you can reduce the memory requirements and increase the speed of the execution of the query. You can accomplish this by creating an anonymous type in the `select` clause and using an object initializer to initialize it with the appropriate properties from the source element. For an example of how to do this, see [Object and Collection Initializers](../../programming-guide/classes-and-structs/object-and-collection-initializers.md). - -## Remarks +As shown in `studentQuery8` in the previous example, sometimes you want the elements of the returned sequence to contain only a subset of the properties of the source elements. By keeping the returned sequence as small as possible, you reduce the memory requirements and increase the speed of the execution of the query. You can accomplish this goal by creating an anonymous type in the `select` clause and using an object initializer to initialize it with the appropriate properties from the source element. For an example of how to do this, see [Object and Collection Initializers](../../programming-guide/classes-and-structs/object-and-collection-initializers.md). At compile time, the `select` clause is translated to a method call to the standard query operator. diff --git a/docs/csharp/language-reference/keywords/set.md b/docs/csharp/language-reference/keywords/set.md index aab81ecd64f0b..8eafee45c90c9 100644 --- a/docs/csharp/language-reference/keywords/set.md +++ b/docs/csharp/language-reference/keywords/set.md @@ -1,7 +1,7 @@ --- description: "The C# set keyword declares a set accessor in a property or indexer. It defines the code to set the value of the property or indexed property." title: "The `set` keyword: property accessor" -ms.date: 11/18/2025 +ms.date: 01/22/2026 f1_keywords: - "set" - "set_CSharpKeyword" @@ -12,14 +12,16 @@ helpviewer_keywords: The `set` keyword defines an *accessor* method in a property or indexer that assigns a value to the property or the indexer element. For more information and examples, see [Properties](../../programming-guide/classes-and-structs/properties.md), [Automatically implemented properties](../../programming-guide/classes-and-structs/auto-implemented-properties.md), and [Indexers](../../programming-guide/indexers/index.md). -For simple cases in which a property's `get` and `set` accessors perform no other operation than setting or retrieving a value in a private backing field, you can use automatically implemented properties. The following example implements `Hours` as an automatically implemented property. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +For simple cases where a property's `get` and `set` accessors perform no other operation than setting or retrieving a value in a private backing field, use automatically implemented properties. The following example implements `Hours` as an automatically implemented property. :::code language="csharp" source="./snippets/PropertyAccessors.cs" id="AutoImplementedProperties"::: > [!IMPORTANT] -> Automatically implemented properties aren't allowed for [interface property declarations](../../programming-guide/classes-and-structs/interface-properties.md) or the implementing declaration for a [partial property](./partial-member.md). The compiler interprets syntax matching an automatically implemented property as the declaring declaration, not an implementing declaration. +> You can't use automatically implemented properties for [interface property declarations](../../programming-guide/classes-and-structs/interface-properties.md) or the implementing declaration for a [partial property](./partial-member.md). The compiler interprets syntax matching an automatically implemented property as the declaring declaration, not an implementing declaration. -You might find that you need to implement one of the accessor bodies. The `field` keyword, added in C# 14, declares a *field backed property*. You can use a field backed property to let the compiler generate one accessor while you write the other by hand. You use the `field` keyword to access the compiler synthesized backing field: +You might need to implement one of the accessor bodies. The `field` keyword, added in C# 14, declares a *field backed property*. Use a field backed property to let the compiler generate one accessor while you write the other by hand. Use the `field` keyword to access the compiler synthesized backing field: :::code language="csharp" source="./snippets/PropertyAccessors.cs" id="FieldBackedProperty"::: diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Common.cs b/docs/csharp/language-reference/keywords/snippets/Common.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Common.cs rename to docs/csharp/language-reference/keywords/snippets/Common.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Orderby.cs b/docs/csharp/language-reference/keywords/snippets/Orderby.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Orderby.cs rename to docs/csharp/language-reference/keywords/snippets/Orderby.cs diff --git a/samples/snippets/csharp/language-reference/keywords/async/wpf/App.xaml b/docs/csharp/language-reference/keywords/snippets/async/wpf/App.xaml similarity index 100% rename from samples/snippets/csharp/language-reference/keywords/async/wpf/App.xaml rename to docs/csharp/language-reference/keywords/snippets/async/wpf/App.xaml diff --git a/samples/snippets/csharp/language-reference/keywords/async/wpf/App.xaml.cs b/docs/csharp/language-reference/keywords/snippets/async/wpf/App.xaml.cs similarity index 100% rename from samples/snippets/csharp/language-reference/keywords/async/wpf/App.xaml.cs rename to docs/csharp/language-reference/keywords/snippets/async/wpf/App.xaml.cs diff --git a/samples/snippets/csharp/language-reference/keywords/async/wpf/MainWindow.xaml b/docs/csharp/language-reference/keywords/snippets/async/wpf/MainWindow.xaml similarity index 100% rename from samples/snippets/csharp/language-reference/keywords/async/wpf/MainWindow.xaml rename to docs/csharp/language-reference/keywords/snippets/async/wpf/MainWindow.xaml diff --git a/samples/snippets/csharp/language-reference/keywords/async/wpf/MainWindow.xaml.cs b/docs/csharp/language-reference/keywords/snippets/async/wpf/MainWindow.xaml.cs similarity index 100% rename from samples/snippets/csharp/language-reference/keywords/async/wpf/MainWindow.xaml.cs rename to docs/csharp/language-reference/keywords/snippets/async/wpf/MainWindow.xaml.cs diff --git a/samples/snippets/csharp/language-reference/keywords/when/catch.cs b/docs/csharp/language-reference/keywords/snippets/catch.cs similarity index 100% rename from samples/snippets/csharp/language-reference/keywords/when/catch.cs rename to docs/csharp/language-reference/keywords/snippets/catch.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/csrefKeywordsContextual.cs b/docs/csharp/language-reference/keywords/snippets/csrefKeywordsContextual.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/csrefKeywordsContextual.cs rename to docs/csharp/language-reference/keywords/snippets/csrefKeywordsContextual.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsLiteral/CS/csrefKeywordsLiteral.cs b/docs/csharp/language-reference/keywords/snippets/csrefKeywordsLiteral.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsLiteral/CS/csrefKeywordsLiteral.cs rename to docs/csharp/language-reference/keywords/snippets/csrefKeywordsLiteral.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs b/docs/csharp/language-reference/keywords/snippets/csrefKeywordsModifiers.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs rename to docs/csharp/language-reference/keywords/snippets/csrefKeywordsModifiers.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperators.cs b/docs/csharp/language-reference/keywords/snippets/csrefKeywordsOperators.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperators.cs rename to docs/csharp/language-reference/keywords/snippets/csrefKeywordsOperators.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/From.cs b/docs/csharp/language-reference/keywords/snippets/from.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/From.cs rename to docs/csharp/language-reference/keywords/snippets/from.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs b/docs/csharp/language-reference/keywords/snippets/group.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs rename to docs/csharp/language-reference/keywords/snippets/group.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Into.cs b/docs/csharp/language-reference/keywords/snippets/into.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Into.cs rename to docs/csharp/language-reference/keywords/snippets/into.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Join.cs b/docs/csharp/language-reference/keywords/snippets/join.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Join.cs rename to docs/csharp/language-reference/keywords/snippets/join.cs diff --git a/docs/csharp/language-reference/keywords/snippets/keywords.csproj b/docs/csharp/language-reference/keywords/snippets/keywords.csproj index a0cd2fda66ab0..4a1f8644d374d 100644 --- a/docs/csharp/language-reference/keywords/snippets/keywords.csproj +++ b/docs/csharp/language-reference/keywords/snippets/keywords.csproj @@ -2,12 +2,13 @@ enable - Exe - net10.0 + WinExe + net10.0-windows enable true Keywords.Program False + true diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsTypes/CS/keywordsTypes.cs b/docs/csharp/language-reference/keywords/snippets/keywordsTypes.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsTypes/CS/keywordsTypes.cs rename to docs/csharp/language-reference/keywords/snippets/keywordsTypes.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Let.cs b/docs/csharp/language-reference/keywords/snippets/let.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Let.cs rename to docs/csharp/language-reference/keywords/snippets/let.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Select.cs b/docs/csharp/language-reference/keywords/snippets/select.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Select.cs rename to docs/csharp/language-reference/keywords/snippets/select.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csvariancekeywords/cs/program.cs b/docs/csharp/language-reference/keywords/snippets/variance.cs similarity index 96% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/csvariancekeywords/cs/program.cs rename to docs/csharp/language-reference/keywords/snippets/variance.cs index 9de5bd54cd26f..87802f99ee8b7 100644 --- a/samples/snippets/csharp/VS_Snippets_VBCSharp/csvariancekeywords/cs/program.cs +++ b/docs/csharp/language-reference/keywords/snippets/variance.cs @@ -2,14 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Windows.Forms; - -class Program -{ - static void Main(string[] args) - { - } -} +using System.Windows; +using System.Windows.Controls; namespace n1 { diff --git a/samples/snippets/csharp/language-reference/keywords/volatile/Program.cs b/docs/csharp/language-reference/keywords/snippets/volatile.cs similarity index 100% rename from samples/snippets/csharp/language-reference/keywords/volatile/Program.cs rename to docs/csharp/language-reference/keywords/snippets/volatile.cs diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Where.cs b/docs/csharp/language-reference/keywords/snippets/where.cs similarity index 100% rename from samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Where.cs rename to docs/csharp/language-reference/keywords/snippets/where.cs diff --git a/docs/csharp/language-reference/keywords/statement-keywords.md b/docs/csharp/language-reference/keywords/statement-keywords.md index c149f831c5eca..71efd51f09145 100644 --- a/docs/csharp/language-reference/keywords/statement-keywords.md +++ b/docs/csharp/language-reference/keywords/statement-keywords.md @@ -1,26 +1,42 @@ --- description: "Statement keywords - C# Reference" title: "Statement keywords" -ms.date: 07/20/2015 +ms.date: 01/22/2026 helpviewer_keywords: - "keywords [C#], statements" - "statements [C#]" -ms.assetid: fad0c004-e282-4ec8-a127-bca7fd7a0b6f --- # Statement keywords (C# Reference) -Statements are program instructions. Except as described in the topics referenced in the following table, statements are executed in sequence. The following table lists the C# statement keywords. For more information about statements that are not expressed with any keyword, see [Statements](../../programming-guide/statements-expressions-operators/statements.md). +Statements are program instructions. Except as described in the topics referenced in the following list, the program executes statements in sequence. The following list shows the C# statement keywords. For more information about statements that don't use a keyword, see [Statements](../../programming-guide/statements-expressions-operators/statements.md). -|Category|C# keywords| -|--------------|------------------| -|[Selection statements](../statements/selection-statements.md)|`if`, `switch`| -|[Iteration statements](../statements/iteration-statements.md)|`do`, `for`, `foreach`, `while`| -|[Jump statements](../statements/jump-statements.md)|`break`, `continue`, `goto`, `return`| -|[Exception-handling statements](../statements/exception-handling-statements.md)|`throw`, `try-catch`, `try-finally`, `try-catch-finally`| -|[checked and unchecked statements](../statements/checked-and-unchecked.md)|`checked`, `unchecked`| -|[fixed statement](../statements/fixed.md)|`fixed`| -|[lock statement](../statements/lock.md)|`lock`| -|[yield statement](../statements/yield.md)|`yield`| +- [Selection statements](../statements/selection-statements.md) + - `if` + - `switch` +- [Iteration statements](../statements/iteration-statements.md) + - `do` + - `for` + - `foreach` + - `while` +- [Jump statements](../statements/jump-statements.md) + - `break` + - `continue` + - `goto` + - `return` +- [Exception-handling statements](../statements/exception-handling-statements.md) + - `throw` + - `try-catch` + - `try-finally` + - `try-catch-finally` +- [checked and unchecked statements](../statements/checked-and-unchecked.md) + - `checked` + - `unchecked` +- [fixed statement](../statements/fixed.md) + - `fixed` +- [lock statement](../statements/lock.md) + - `lock` +- [yield statement](../statements/yield.md) + - `yield` ## See also diff --git a/docs/csharp/language-reference/keywords/static.md b/docs/csharp/language-reference/keywords/static.md index 1f6d5c43abc9c..ce581fa919fe4 100644 --- a/docs/csharp/language-reference/keywords/static.md +++ b/docs/csharp/language-reference/keywords/static.md @@ -1,37 +1,34 @@ --- description: "static modifier - C# Reference" title: "static modifier" -ms.date: 09/25/2020 +ms.date: 01/22/2026 f1_keywords: - "static" - "static_CSharpKeyword" helpviewer_keywords: - "static keyword [C#]" -ms.assetid: 5509e215-2183-4da3-bab4-6b7e607a4fdf --- # static (C# Reference) -This page covers the `static` modifier keyword. The `static` keyword is also part of the [`using static`](using-directive.md) directive. +This article covers the `static` modifier keyword. The `static` keyword is also part of the [`using static`](using-directive.md) directive. -Use the `static` modifier to declare a static member, which belongs to the type itself rather than to a specific object. The `static` modifier can be used to declare `static` classes. In classes, interfaces, and structs, you may add the `static` modifier to fields, methods, properties, operators, events, and constructors. The `static` modifier can't be used with indexers or finalizers. For more information, see [Static Classes and Static Class Members](../../programming-guide/classes-and-structs/static-classes-and-static-class-members.md). +Use the `static` modifier to declare a static member, which belongs to the type itself rather than to a specific object. Use the `static` modifier to declare `static` classes. In classes, interfaces, and structs, you can add the `static` modifier to fields, methods, properties, operators, events, and constructors. You can't use the `static` modifier with indexers or finalizers. For more information, see [Static Classes and Static Class Members](../../programming-guide/classes-and-structs/static-classes-and-static-class-members.md). You can add the `static` modifier to a [local function](../../programming-guide/classes-and-structs/local-functions.md). A static local function can't capture local variables or instance state. -[!code-csharp[csrefKeywordsModifiers#28](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#28)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="28"::: You can add the `static` modifier to a [lambda expression](../operators/lambda-expressions.md) or [anonymous method](../operators/delegate-operator.md). A static lambda or anonymous method can't capture local variables or instance state. -[!code-csharp[csrefKeywordsModifiers#29](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#29)] - -## Example - static class +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="29"::: The following class is declared as `static` and contains only `static` methods: -[!code-csharp[csrefKeywordsModifiers#18](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#18)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="18"::: -A constant or type declaration is implicitly a `static` member. A `static` member can't be referenced through an instance. Instead, it's referenced through the type name. For example, consider the following class: +A constant or type declaration is implicitly a `static` member. You can't reference a `static` member through an instance. Instead, reference it through the type name. For example, consider the following class: -[!code-csharp[csrefKeywordsModifiers#19](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#19)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="19"::: To refer to the `static` member `x`, use the fully qualified name, `MyBaseC.MyStruct.x`, unless the member is accessible from the same scope: @@ -41,28 +38,24 @@ Console.WriteLine(MyBaseC.MyStruct.x); While an instance of a class contains a separate copy of all instance fields of the class, there's only one copy of each `static` field. For generic types, each closed generic type has its own copy of static fields. Static fields marked with have one copy per thread. -It isn't possible to use [`this`](this.md) to reference `static` methods or property accessors. +You can't use [`this`](this.md) to reference `static` methods or property accessors. -If the `static` keyword is applied to a class, all the members of the class must be `static`. +If you apply the `static` keyword to a class, all the members of the class must be `static`. -Classes, interfaces, and `static` classes may have `static` constructors. A `static` constructor is called at some point between when the program starts and the class is instantiated. +Classes, interfaces, and `static` classes can have `static` constructors. A `static` constructor is called at some point between when the program starts and the class is instantiated. > [!NOTE] > The `static` keyword has more limited uses than in C++. To compare with the C++ keyword, see [Storage classes (C++)](/cpp/cpp/storage-classes-cpp#static). To demonstrate `static` members, consider a class that represents a company employee. Assume that the class contains a method to count employees and a field to store the number of employees. Both the method and the field don't belong to any one employee instance. Instead, they belong to the class of employees as a whole. They should be declared as `static` members of the class. -## Example - static field and method - This example reads the name and ID of a new employee, increments the employee counter by one, and displays the information for the new employee and the new number of employees. This program reads the current number of employees from the keyboard. -[!code-csharp[csrefKeywordsModifiers#20](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#20)] - -## Example - static initialization +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="20"::: -This example shows that you can initialize a `static` field by using another `static` field that is not yet declared. The results will be undefined until you explicitly assign a value to the `static` field. +This example shows that you can initialize a `static` field by using another `static` field that isn't yet declared. The results are undefined until you explicitly assign a value to the `static` field. -[!code-csharp[csrefKeywordsModifiers#21](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#21)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="21"::: ## C# language specification diff --git a/docs/csharp/language-reference/keywords/this.md b/docs/csharp/language-reference/keywords/this.md index 41ebf325ffc61..13e3acfce331d 100644 --- a/docs/csharp/language-reference/keywords/this.md +++ b/docs/csharp/language-reference/keywords/this.md @@ -1,7 +1,7 @@ --- title: "The this keyword" description: The `this` keyword clarifies access to the current instance of a type, or declares an indexer on the type. -ms.date: 04/17/2025 +ms.date: 01/22/2026 f1_keywords: - "this" - "this_CSharpKeyword" @@ -10,30 +10,29 @@ helpviewer_keywords: --- # The this keyword -The `this` keyword refers to the current instance of the class and is also used as a modifier of the first parameter of an extension method. +The `this` keyword refers to the current instance of the class. It also serves as a modifier for the first parameter of an extension method. > [!NOTE] > This article discusses the use of `this` to refer to the receiver instance in the current member. For more information about its use in extension methods, see the [`extension`](./extension.md) keyword. -The following are common uses of `this`: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -- To qualify members hidden by similar names, for example: +Common uses of `this` include: +- Qualifying members hidden by similar names, such as: :::code language="csharp" source="./snippets/csrefKeywordsAccess.cs" id="snippet4"::: - -- To pass an object as a parameter to other methods, for example: +- Passing an object as a parameter to other methods. ```csharp CalcTax(this); ``` -- To declare [indexers](../../programming-guide/indexers/index.md), for example: - +- Declaring [indexers](../../programming-guide/indexers/index.md), such as: :::code language="csharp" source="./snippets/csrefKeywordsAccess.cs" id="snippet5"::: -Static member functions, because they exist at the class level and not as part of an object, don't have a `this` pointer. It's an error to refer to `this` in a static method. +Static member functions exist at the class level and not as part of an object. They don't have a `this` pointer. Referring to `this` in a static method is an error. -In this example, the parameters `name`, and `alias` hide fields with the same names. The `this` keyword qualifies those variables as `Employee` class members. The `this` keyword also specifies the object for the method `CalcTax`, which belongs to another class. +In the following example, the parameters `name` and `alias` hide fields with the same names. The `this` keyword qualifies those variables as `Employee` class members. The `this` keyword also specifies the object for the method `CalcTax`, which belongs to another class. :::code language="csharp" source="./snippets/csrefKeywordsAccess.cs" id="snippet3"::: diff --git a/docs/csharp/language-reference/keywords/unsafe.md b/docs/csharp/language-reference/keywords/unsafe.md index 932a08489d3ea..36f60fff129ab 100644 --- a/docs/csharp/language-reference/keywords/unsafe.md +++ b/docs/csharp/language-reference/keywords/unsafe.md @@ -1,19 +1,20 @@ --- description: "unsafe keyword - C# Reference" title: "unsafe keyword" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "unsafe_CSharpKeyword" - "unsafe" helpviewer_keywords: - "unsafe keyword [C#]" -ms.assetid: 7e818009-1c6e-4b9e-b769-3728a01586a0 --- # unsafe (C# Reference) The `unsafe` keyword denotes an unsafe context, which is required for any operation involving pointers. For more information, see [Unsafe Code and Pointers](../unsafe-code.md). -You can use the `unsafe` modifier in the declaration of a type or a member. The entire textual extent of the type or member is therefore considered an unsafe context. For example, the following is a method declared with the `unsafe` modifier: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +Use the `unsafe` modifier in the declaration of a type or a member. The entire textual extent of the type or member is an unsafe context. For example, the following method is declared with the `unsafe` modifier: ```csharp unsafe static void FastCopy(byte[] src, byte[] dst, int count) @@ -22,13 +23,13 @@ unsafe static void FastCopy(byte[] src, byte[] dst, int count) } ``` -The scope of the unsafe context extends from the parameter list to the end of the method, so pointers can also be used in the parameter list: +The scope of the unsafe context extends from the parameter list to the end of the method, so you can also use pointers in the parameter list: ```csharp unsafe static void FastCopy ( byte* ps, byte* pd, int count ) {...} ``` -You can also use an unsafe block to enable the use of an unsafe code inside this block. For example: +You can also use an unsafe block to enable the use of unsafe code inside this block. For example: ```csharp unsafe @@ -37,11 +38,11 @@ unsafe } ``` -To compile unsafe code, you must specify the [**AllowUnsafeBlocks**](../compiler-options/language.md#allowunsafeblocks) compiler option. Unsafe code is not verifiable by the common language runtime. +To compile unsafe code, you must specify the [**AllowUnsafeBlocks**](../compiler-options/language.md#allowunsafeblocks) compiler option. The common language runtime can't verify unsafe code. ## Example -[!code-csharp[csrefKeywordsModifiers#22](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#22)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="22"::: ## C# language specification diff --git a/docs/csharp/language-reference/keywords/using-directive.md b/docs/csharp/language-reference/keywords/using-directive.md index 5838320f2e559..82530486f736f 100644 --- a/docs/csharp/language-reference/keywords/using-directive.md +++ b/docs/csharp/language-reference/keywords/using-directive.md @@ -1,7 +1,7 @@ --- description: "The `using` directive imports types from a namespace, or creates an alias for a given type. Using directives enable you to use simple names for types instead of the fully qualified type name." title: "The using directive: Import types from a namespace" -ms.date: 11/24/2025 +ms.date: 01/22/2026 f1_keywords: - "using_CSharpKeyword" - "using-static_CSharpKeyword" @@ -11,7 +11,7 @@ helpviewer_keywords: --- # The `using` directive -The `using` directive allows you to use types defined in a namespace without specifying the fully qualified namespace of that type. In its basic form, the `using` directive imports all the types from a single namespace, as shown in the following example: +The `using` directive enables you to use types defined in a namespace without specifying the fully qualified namespace of that type. In its basic form, the `using` directive imports all the types from a single namespace, as shown in the following example: ```csharp using System.Text; @@ -32,6 +32,8 @@ using Project = PC.MyCompany.Project; You can use the `global` modifier on a *using alias directive*. +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + > [!NOTE] > The `using` keyword is also used to create *`using` statements*, which help ensure that objects such as files and fonts are handled correctly. For more information about the *`using` statement*, see [`using` statement](../statements/using.md). @@ -50,22 +52,22 @@ Create a `using` directive to use the types in a namespace without having to spe ## The `global` modifier -Adding the `global` modifier to a `using` directive means that using is applied to all files in the compilation (typically a project): +When you add the `global` modifier to a `using` directive, you apply the using to all files in the compilation (typically a project): ```csharp global using ; ``` -Where *fully-qualified-namespace* is the fully qualified name of the namespace whose types can be referenced without specifying the namespace. +Where *fully-qualified-namespace* is the fully qualified name of the namespace whose types you can reference without specifying the namespace. A *global using* directive can appear at the beginning of any source code file. All `global using` directives in a single file must appear before: - All `using` directives without the `global` modifier. - All namespace and type declarations in the file. -You can add `global using` directives to any source file. Typically, you want to keep them in a single location. The order of `global using` directives doesn't matter, either in a single file, or between files. +You can add `global using` directives to any source file. Typically, you keep them in a single location. The order of `global using` directives doesn't matter, either in a single file or between files. -The `global` modifier can be combined with the `static` modifier. The `global` modifier can be applied to a *using alias directive*. In both cases, the directive's scope is all files in the current compilation. The following example enables using all the methods declared in the in all files in your project: +You can combine the `global` modifier with the `static` modifier. You can apply the `global` modifier to a *using alias directive*. In both cases, the directive's scope is all files in the current compilation. The following example enables using all the methods declared in the in all files in your project: ```csharp global using static System.Math; @@ -86,11 +88,11 @@ The `using static` directive names a type whose static members and nested types using static ; ``` -The `` is the name of the type whose static members and nested types can be referenced without specifying a type name. If you don't provide a fully qualified type name (the full namespace name along with the type name), C# generates compiler error [CS0246](../compiler-messages/assembly-references.md): "The type or namespace name 'type/namespace' couldn't be found (are you missing a using directive or an assembly reference?)". +The `` is the name of the type whose static members and nested types you can reference without specifying a type name. If you don't provide a fully qualified type name (the full namespace name along with the type name), C# generates compiler error [CS0246](../compiler-messages/assembly-references.md): "The type or namespace name 'type/namespace' couldn't be found (are you missing a using directive or an assembly reference?)". -If the `using static` directive is applied within the context of a namespace (either file-scoped or nested in a `namespace` block, it isn't necessary to fully qualify the type. +If you apply the `using static` directive within the context of a namespace (either file-scoped or nested in a `namespace` block), you don't need to fully qualify the type. -The `using static` directive applies to any type that has static members (or nested types), even if it also has instance members. However, instance members can only be invoked through the type instance. +The `using static` directive applies to any type that has static members (or nested types), even if it also has instance members. However, you can only invoke instance members through the type instance. You can access static members of a type without having to qualify the access with the type name: @@ -114,7 +116,7 @@ By eliminating the need to explicitly reference the class eac :::code language="csharp" source="./snippets/using-static2.cs"::: -`using static` imports only accessible static members and nested types declared in the specified type. Inherited members aren't imported. You can import from any named type with a `using static` directive, including Visual Basic modules. If F# top-level functions appear in metadata as static members of a named type whose name is a valid C# identifier, then the F# functions can be imported. +`using static` imports only accessible static members and nested types declared in the specified type. Inherited members aren't imported. You can import from any named type with a `using static` directive, including Visual Basic modules. If F# top-level functions appear in metadata as static members of a named type whose name is a valid C# identifier, the F# functions can be imported. `using static` makes extension members declared in the specified type available for extension member lookup. However, the names of the extension members aren't imported into scope for unqualified reference in code. @@ -124,9 +126,9 @@ The following example uses the `using static` directive to make the static membe :::code language="csharp" source="./snippets/using-static3.cs" id="Snippet1"::: -In the example, the `using static` directive could also be applied to the type. Adding that directive would make it possible to call the method without specifying a type name. However, using `TryParse` without a type name creates less readable code, since it becomes necessary to check the `using static` directives to determine which numeric type's `TryParse` method is called. +In the example, you could also apply the `using static` directive to the type. Adding that directive would make it possible to call the method without specifying a type name. However, using `TryParse` without a type name creates less readable code, since it becomes necessary to check the `using static` directives to determine which numeric type's `TryParse` method is called. -`using static` also applies to `enum` types. By adding `using static` with the enum, the type is no longer required to use the enum members. +`using static` also applies to `enum` types. By adding `using static` with the enum, you no longer need to use the enum type to access its members. ```csharp using static Color; @@ -149,7 +151,7 @@ class Program ## The `using` alias -Create a `using` alias directive to make it easier to qualify an identifier to a namespace or type. In any `using` directive, the fully qualified namespace or type must be used regardless of the `using` directives that come before it. No `using` alias can be used in the declaration of a `using` directive. For example, the following example generates a compiler error: +Create a `using` alias directive to make it easier to qualify an identifier to a namespace or type. In any `using` directive, you must use the fully qualified namespace or type regardless of the `using` directives that come before it. You can't use a `using` alias in the declaration of a `using` directive. For example, the following example generates a compiler error: ```csharp using s = System.Text; @@ -170,7 +172,7 @@ Beginning with C# 12, you can create aliases for types that were previously rest ## Qualified alias member -The namespace alias qualifier, `::` provides explicit access to the global namespace or other using aliases potentially hidden by other entities. +The namespace alias qualifier, `::` provides explicit access to the global namespace or other using aliases that other entities might hide. The `global::` ensures that the namespace lookup for the namespace following the `::` token is relative to the global namespace. Otherwise, the token must resolve to a using alias, and the token following the `::` must resolve to a type in that aliased namespace. The following example shows both forms: diff --git a/docs/csharp/language-reference/keywords/using.md b/docs/csharp/language-reference/keywords/using.md index 7a5cb2e742279..486572a54709c 100644 --- a/docs/csharp/language-reference/keywords/using.md +++ b/docs/csharp/language-reference/keywords/using.md @@ -1,24 +1,20 @@ --- title: "using keyword" description: "using keyword - C# reference" -ms.date: 04/05/2019 +ms.date: 01/22/2026 f1_keywords: - "using" helpviewer_keywords: - "using keyword [C#]" -ms.assetid: 124e1a63-2a4b-4132-b269-3b6d8d3ef72d --- # using (C# reference) The `using` keyword has two major uses: - The [`using` statement](../statements/using.md) defines a scope at the end of which an object is disposed: - -:::code language="csharp" source="./snippets/UsingKeywordExample.cs" id="UsingStatement"::: - + :::code language="csharp" source="./snippets/UsingKeywordExample.cs" id="UsingStatement"::: - The [`using` directive](using-directive.md) creates an alias for a namespace or imports types defined in other namespaces: - -:::code language="csharp" source="./snippets/UsingKeywordExample.cs" id="UsingDirective"::: + :::code language="csharp" source="./snippets/UsingKeywordExample.cs" id="UsingDirective"::: ## See also diff --git a/docs/csharp/language-reference/keywords/value.md b/docs/csharp/language-reference/keywords/value.md index 8ffd134325913..5050afb490f8f 100644 --- a/docs/csharp/language-reference/keywords/value.md +++ b/docs/csharp/language-reference/keywords/value.md @@ -9,7 +9,11 @@ helpviewer_keywords: --- # The `value` implicit parameter -The implicit parameter `value` is used in the `set` accessor in [property](../../programming-guide/classes-and-structs/properties.md) and [indexer](../../programming-guide/indexers/index.md) declarations. It's an input parameter of a method. The word `value` references the value that client code is attempting to assign to the property or indexer. In the following example, `TimePeriod2` has a property called `Seconds` that uses the `value` parameter to assign a new string to the backing field `_seconds`. From the point of view of client code, the operation is written as a simple assignment. +The `set` accessor in [property](../../programming-guide/classes-and-structs/properties.md) and [indexer](../../programming-guide/indexers/index.md) declarations uses the implicit parameter `value`. This parameter acts as an input for the method. The word `value` refers to the value that client code tries to assign to the property or indexer. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +In the following example, `TimePeriod2` has a property named `Seconds` that uses the `value` parameter to assign a new string to the backing field `_seconds`. From the point of view of client code, the operation is written as a simple assignment. :::code language="csharp" source="./snippets/PropertyAccessors.cs" id="GetSetExpressions"::: diff --git a/docs/csharp/language-reference/keywords/virtual.md b/docs/csharp/language-reference/keywords/virtual.md index 593467948a9b6..abcc1500fa9f9 100644 --- a/docs/csharp/language-reference/keywords/virtual.md +++ b/docs/csharp/language-reference/keywords/virtual.md @@ -1,17 +1,20 @@ --- description: "virtual - C# Reference" title: "virtual keyword" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "virtual_CSharpKeyword" - "virtual" helpviewer_keywords: - "virtual keyword [C#]" -ms.assetid: 5da9abae-bc1e-434f-8bea-3601b8dcb3b2 --- # virtual (C# Reference) -The `virtual` keyword is used to modify a method, property, indexer, or event declaration and allow for it to be overridden in a derived class. For example, this method can be overridden by any class that inherits it: +Use the `virtual` keyword to modify a method, property, indexer, or event declaration and allow a derived class to override it. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +For example, any class that inherits this method can override it: ```csharp public virtual double Area() @@ -20,17 +23,15 @@ public virtual double Area() } ``` -The implementation of a virtual member can be changed by an [overriding member](override.md) in a derived class. For more information about how to use the `virtual` keyword, see [Versioning with the Override and New Keywords](../../programming-guide/classes-and-structs/versioning-with-the-override-and-new-keywords.md) and [Knowing When to Use Override and New Keywords](../../programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords.md). - -## Remarks +An [overriding member](override.md) in a derived class can change the implementation of a virtual member. For more information about how to use the `virtual` keyword, see [Versioning with the Override and New Keywords](../../programming-guide/classes-and-structs/versioning-with-the-override-and-new-keywords.md) and [Knowing When to Use Override and New Keywords](../../programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords.md). -When a virtual method is invoked, the run-time type of the object is checked for an overriding member. The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member. +When you invoke a virtual method, the runtime checks the type of the object for an overriding member. It calls the overriding member in the most derived class. If no derived class overrides the member, the original member is called. -By default, methods are non-virtual. You cannot override a non-virtual method. +By default, methods are non-virtual. You can't override a non-virtual method. The following example shows a virtual property: -[!code-csharp[csrefKeywordsModifiers#26](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#26)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="26"::: Virtual properties behave like virtual methods, except for the differences in declaration and invocation syntax. @@ -38,9 +39,9 @@ Virtual properties behave like virtual methods, except for the differences in de ## Example -In this example, the `Shape` class contains the two coordinates `x`, `y`, and the `Area()` virtual method. Different shape classes such as `Circle`, `Cylinder`, and `Sphere` inherit the `Shape` class, and the surface area is calculated for each figure. Each derived class has its own override implementation of `Area()`. +In this example, the `Shape` class contains the two coordinates `x` and `y`, and the `Area()` virtual method. Different shape classes such as `Circle`, `Cylinder`, and `Sphere` inherit the `Shape` class, and the surface area is calculated for each figure. Each derived class has its own override implementation of `Area()`. -Notice that the inherited classes `Circle`, `Cylinder`, and `Sphere` all use constructors that initialize the base class, as shown in the following declaration. +The inherited classes `Circle`, `Cylinder`, and `Sphere` all use constructors that initialize the base class, as shown in the following declaration. ```csharp public Cylinder(double r, double h): base(r, h) {} @@ -48,7 +49,7 @@ public Cylinder(double r, double h): base(r, h) {} The following program calculates and displays the appropriate area for each figure by invoking the appropriate implementation of the `Area()` method, according to the object that is associated with the method. -[!code-csharp[csrefKeywordsModifiers#23](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.cs#23)] +:::code language="csharp" source="./snippets/csrefKeywordsModifiers.cs" id="23"::: ## C# language specification diff --git a/docs/csharp/language-reference/keywords/volatile.md b/docs/csharp/language-reference/keywords/volatile.md index 121e285819641..a347c61e9e3d0 100644 --- a/docs/csharp/language-reference/keywords/volatile.md +++ b/docs/csharp/language-reference/keywords/volatile.md @@ -1,61 +1,60 @@ --- description: "volatile - C# Reference" title: "volatile keyword" -ms.date: 10/24/2018 +ms.date: 01/22/2026 f1_keywords: - "volatile_CSharpKeyword" - "volatile" helpviewer_keywords: - "volatile keyword [C#]" -ms.assetid: 78089bc7-7b38-4cfd-9e49-87ac036af009 --- # volatile (C# Reference) -The `volatile` keyword indicates that a field might be modified by multiple threads that are executing at the same time. The compiler, the runtime system, and even hardware may rearrange reads and writes to memory locations for performance reasons. Fields that are declared `volatile` are excluded from certain kinds of optimizations. There is no guarantee of a single total ordering of volatile writes as seen from all threads of execution. For more information, see the class. +Use the `volatile` keyword to indicate that a field might be modified by multiple threads that are executing at the same time. For performance reasons, the compiler, the runtime system, and even hardware might rearrange reads and writes to memory locations. Declaring a field as `volatile` excludes it from certain kinds of optimizations. There's no guarantee of a single total ordering of volatile writes as seen from all threads of execution. For more information, see the class. > [!CAUTION] -> The `volatile` keyword is often misunderstood and misused in multithreaded programming. In most scenarios, you should use safer and more reliable alternatives instead of `volatile`. Modern .NET provides better concurrency tools like the class, the [`lock`](../statements/lock.md) statement, or higher-level synchronization primitives. These alternatives provide clearer semantics and stronger guarantees than `volatile`. Consider using `volatile` only in rare, advanced scenarios where you fully understand its limitations and have verified it's the appropriate solution. +> The `volatile` keyword is often misunderstood and misused in multithreaded programming. In most scenarios, use safer and more reliable alternatives instead of `volatile`. Modern .NET provides better concurrency tools like the class, the [`lock`](../statements/lock.md) statement, or higher-level synchronization primitives. These alternatives provide clearer semantics and stronger guarantees than `volatile`. Consider using `volatile` only in rare, advanced scenarios where you fully understand its limitations and have verified it's the appropriate solution. > [!NOTE] -> On a multiprocessor system, a volatile read operation does not guarantee to obtain the latest value written to that memory location by any processor. Similarly, a volatile write operation does not guarantee that the value written would be immediately visible to other processors. +> On a multiprocessor system, a volatile read operation doesn't guarantee to obtain the latest value written to that memory location by any processor. Similarly, a volatile write operation doesn't guarantee that the value written is immediately visible to other processors. -The `volatile` keyword can be applied to fields of these types: +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + +Apply the `volatile` keyword to fields of these types: - Reference types. -- Pointer types (in an unsafe context). Note that although the pointer itself can be volatile, the object that it points to cannot. In other words, you cannot declare a "pointer to volatile." +- Pointer types (in an unsafe context). Although the pointer itself can be volatile, the object that it points to can't be. In other words, you can't declare a "pointer to volatile." - Simple types such as `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `char`, `float`, and `bool`. - An `enum` type with one of the following base types: `byte`, `sbyte`, `short`, `ushort`, `int`, or `uint`. - Generic type parameters known to be reference types. - and . -Other types, including `double` and `long`, cannot be marked `volatile` because reads and writes to fields of those types cannot be guaranteed to be atomic. To protect multi-threaded access to those types of fields, use the class members or protect access using the [`lock`](../statements/lock.md) statement. +You can't mark other types, including `double` and `long`, as `volatile` because reads and writes to fields of those types can't be guaranteed to be atomic. To protect multithreaded access to those types of fields, use the class members or protect access by using the [`lock`](../statements/lock.md) statement. For most multithreaded scenarios, even with supported types, prefer using operations, [`lock`](../statements/lock.md) statements, or other synchronization primitives instead of `volatile`. These alternatives are less prone to subtle concurrency bugs. -The `volatile` keyword can only be applied to fields of a `class` or `struct`. Local variables cannot be declared `volatile`. +You can only apply the `volatile` keyword to fields of a `class` or `struct`. You can't declare local variables as `volatile`. ## Alternatives to volatile -In most cases, you should use one of these safer alternatives instead of `volatile`: +In most cases, use one of these safer alternatives instead of `volatile`: -- ** operations**: Provide atomic operations for numeric types and reference assignments. These are generally faster and provide stronger guarantees than `volatile`. -- **[`lock` statement](../statements/lock.md)**: Provides mutual exclusion and memory barriers. Use for protecting larger critical sections. +- ** operations**: Provide atomic operations for numeric types and reference assignments. These operations are generally faster and provide stronger guarantees than `volatile`. +- **[`lock` statement](../statements/lock.md)**: Provides mutual exclusion and memory barriers. Use it for protecting larger critical sections. - ** class**: Provides explicit volatile read and write operations with clearer semantics than the `volatile` keyword. - **Higher-level synchronization primitives**: Such as , , or concurrent collections from . -The `volatile` keyword doesn't provide atomicity for operations other than assignment, doesn't prevent race conditions, and doesn't provide ordering guarantees for other memory operations. These limitations make it unsuitable for most concurrency scenarios. - -## Example +The `volatile` keyword doesn't provide atomicity for operations other than assignment. It doesn't prevent race conditions, and it doesn't provide ordering guarantees for other memory operations. These limitations make it unsuitable for most concurrency scenarios. The following example shows how to declare a public field variable as `volatile`. -[!code-csharp[declareVolatile](~/samples/snippets/csharp/language-reference/keywords/volatile/Program.cs#Declaration)] +:::code language="csharp" source="./snippets/volatile.cs" id="Declaration"::: The following example demonstrates how an auxiliary or worker thread can be created and used to perform processing in parallel with that of the primary thread. For more information about multithreading, see [Managed Threading](../../../standard/threading/managed-threading-basics.md). -[!code-csharp[declareVolatile](~/samples/snippets/csharp/language-reference/keywords/volatile/Program.cs#Volatile)] +:::code language="csharp" source="./snippets/volatile.cs" id="Volatile"::: -With the `volatile` modifier added to the declaration of `_shouldStop` in place, you'll always get the same results (similar to the excerpt shown in the preceding code). However, without that modifier on the `_shouldStop` member, the behavior is unpredictable. The `DoWork` method may optimize the member access, resulting in reading stale data. Because of the nature of multi-threaded programming, the number of stale reads is unpredictable. Different runs of the program will produce somewhat different results. +When you add the `volatile` modifier to the declaration of `_shouldStop`, you always get the same results (similar to the excerpt shown in the preceding code). However, without that modifier on the `_shouldStop` member, the behavior is unpredictable. The `DoWork` method might optimize the member access, resulting in reading stale data. Because of the nature of multithreaded programming, the number of stale reads is unpredictable. Different runs of the program produce somewhat different results. ## C# language specification diff --git a/docs/csharp/language-reference/keywords/when.md b/docs/csharp/language-reference/keywords/when.md index 9c2ad43a385de..8cb3f6280e10f 100644 --- a/docs/csharp/language-reference/keywords/when.md +++ b/docs/csharp/language-reference/keywords/when.md @@ -1,37 +1,38 @@ --- description: "when contextual keyword - C# reference" title: "when contextual keyword" -ms.date: 03/07/2017 +ms.date: 01/22/2026 f1_keywords: - "when_CSharpKeyword" - "when" helpviewer_keywords: - "when keyword [C#]" -ms.assetid: dd543335-ae37-48ac-9560-bd5f047b9aea --- # when (C# reference) -You use the `when` contextual keyword to specify a filter condition in the following contexts: +Use the `when` contextual keyword to specify a filter condition in the following contexts: - In a catch clause of a [`try-catch`](../statements/exception-handling-statements.md#the-try-catch-statement) or [`try-catch-finally`](../statements/exception-handling-statements.md#the-try-catch-finally-statement) statement. - As a [case guard](../statements/selection-statements.md#case-guards) in the [`switch` statement](../statements/selection-statements.md#the-switch-statement). - As a [case guard](../operators/switch-expression.md#case-guards) in the [`switch` expression](../operators/switch-expression.md). +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] + ## `when` in a catch clause -The `when` keyword can be used in a catch clause to specify a condition that must be true for the handler for a specific exception to execute. Its syntax is: +Use the `when` keyword in a catch clause to specify a condition that must be true for the handler for a specific exception to execute. Its syntax is: ```csharp catch (ExceptionType [e]) when (expr) ``` -where *expr* is an expression that evaluates to a Boolean value. If it returns `true`, the exception handler executes; if `false`, it does not. +where *expr* is an expression that evaluates to a Boolean value. If it returns `true`, the exception handler executes; if `false`, it doesn't. Exception filters with the `when` keyword provide several advantages over traditional exception handling approaches, including better debugging support and performance benefits. For a detailed explanation of how exception filters preserve the call stack and improve debugging, see [Exception filters vs. traditional exception handling](../statements/exception-handling-statements.md#exception-filters-vs-traditional-exception-handling). The following example uses the `when` keyword to conditionally execute handlers for an depending on the text of the exception message. -[!code-csharp[when-with-catch](~/samples/snippets/csharp/language-reference/keywords/when/catch.cs)] +:::code language="csharp" source="./snippets/catch.cs"::: ## See also diff --git a/docs/csharp/language-reference/keywords/where-clause.md b/docs/csharp/language-reference/keywords/where-clause.md index 5b6a5871dc2ce..e62203d28fd96 100644 --- a/docs/csharp/language-reference/keywords/where-clause.md +++ b/docs/csharp/language-reference/keywords/where-clause.md @@ -1,43 +1,38 @@ --- description: "where clause - C# Reference" title: "where clause" -ms.date: 07/20/2015 +ms.date: 01/22/2026 f1_keywords: - "whereclause_CSharpKeyword" helpviewer_keywords: - "where keyword [C#]" - "where clause [C#]" -ms.assetid: 7f9bf952-7744-4f91-b676-cddb55d107c3 --- # where clause (C# Reference) -The `where` clause is used in a query expression to specify which elements from the data source will be returned in the query expression. It applies a Boolean condition (*predicate*) to each source element (referenced by the range variable) and returns those for which the specified condition is true. A single query expression may contain multiple `where` clauses and a single clause may contain multiple predicate subexpressions. +Use the `where` clause in a query expression to specify which elements from the data source to return. It applies a Boolean condition (*predicate*) to each source element (referenced by the range variable) and returns those elements for which the specified condition is true. A single query expression can contain multiple `where` clauses, and a single clause can contain multiple predicate subexpressions. -## Example 1 +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] -In the following example, the `where` clause filters out all numbers except those that are less than five. If you remove the `where` clause, all numbers from the data source would be returned. The expression `num < 5` is the predicate that is applied to each element. +In the following example, the `where` clause filters out all numbers except those that are less than five. If you remove the `where` clause, the query returns all numbers from the data source. The expression `num < 5` is the predicate that the query applies to each element. -[!code-csharp[cscsrefQueryKeywords#5](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Where.cs#5)] - -## Example 2 +:::code language="csharp" source="./snippets/where.cs" id="5"::: Within a single `where` clause, you can specify as many predicates as necessary by using the [&&](../operators/boolean-logical-operators.md#conditional-logical-and-operator-) and [||](../operators/boolean-logical-operators.md#conditional-logical-or-operator-) operators. In the following example, the query specifies two predicates in order to select only the even numbers that are less than five. -[!code-csharp[cscsrefQueryKeywords#6](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Where.cs#6)] - -## Example 3 +:::code language="csharp" source="./snippets/where.cs" id="6"::: -A `where` clause may contain one or more methods that return Boolean values. In the following example, the `where` clause uses a method to determine whether the current value of the range variable is even or odd. +A `where` clause can contain one or more methods that return Boolean values. In the following example, the `where` clause uses a method to determine whether the current value of the range variable is even or odd. -[!code-csharp[cscsrefQueryKeywords#7](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Where.cs#7)] +:::code language="csharp" source="./snippets/where.cs" id="7"::: ## Remarks -The `where` clause is a filtering mechanism. It can be positioned almost anywhere in a query expression, except it cannot be the first or last clause. A `where` clause may appear either before or after a [group](group-clause.md) clause depending on whether you have to filter the source elements before or after they are grouped. +The `where` clause is a filtering mechanism. You can position it almost anywhere in a query expression, except it can't be the first or last clause. A `where` clause can appear either before or after a [group](group-clause.md) clause depending on whether you need to filter the source elements before or after they are grouped. -If a specified predicate is not valid for the elements in the data source, a compile-time error will result. This is one benefit of the strong type-checking provided by LINQ. +If you specify a predicate that's not valid for the elements in the data source, the query results in a compile-time error. This error is one benefit of the strong type-checking that LINQ provides. -At compile time the `where` keyword is converted into a call to the Standard Query Operator method. +At compile time, the `where` keyword is converted into a call to the Standard Query Operator method. ## See also diff --git a/docs/csharp/language-reference/keywords/where-generic-type-constraint.md b/docs/csharp/language-reference/keywords/where-generic-type-constraint.md index 41d6398125641..60398bca12177 100644 --- a/docs/csharp/language-reference/keywords/where-generic-type-constraint.md +++ b/docs/csharp/language-reference/keywords/where-generic-type-constraint.md @@ -1,8 +1,7 @@ --- description: "where (generic type constraint) - C# Reference" title: "where (generic type constraint)" - -ms.date: 11/24/2024 +ms.date: 01/22/2026 f1_keywords: - "whereconstraint" - "whereconstraint_CSharpKeyword" @@ -15,7 +14,9 @@ helpviewer_keywords: --- # where (generic type constraint) (C# Reference) -The `where` clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type. They declare capabilities that the type argument must have, and must be placed after any declared base class or implemented interfaces. +In a generic definition, use the `where` clause to specify constraints on the types that you use as arguments for type parameters in a generic type, method, delegate, or local function. You can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type. These constraints declare capabilities that the type argument must have. Place the `where` clause after any declared base class or implemented interfaces. + +[!INCLUDE[csharp-version-note](../includes/initial-version.md)] For example, you can declare a generic class, `AGenericClass`, such that the type parameter `T` implements the interface: @@ -24,11 +25,11 @@ For example, you can declare a generic class, `AGenericClass`, such that the typ > [!NOTE] > For more information on the where clause in a query expression, see [where clause](where-clause.md). -The `where` clause can also include a base class constraint. The base class constraint states that a type to be used as a type argument for that generic type has the specified class as a base class, or is that base class. If the base class constraint is used, it must appear before any other constraints on that type parameter. Some types are disallowed as a base class constraint: , , and . The following example shows the types that can now be specified as a base class: +The `where` clause can also include a base class constraint. The base class constraint states that a type to use as a type argument for that generic type has the specified class as a base class, or is that base class. If you use the base class constraint, it must appear before any other constraints on that type parameter. Some types are disallowed as a base class constraint: , , and . The following example shows the types that you can specify as a base class: :::code language="csharp" source="snippets/GenericWhereConstraints.cs" ID="Snippet2"::: -In a nullable context, the nullability of the base class type is enforced. If the base class is non-nullable (for example `Base`), the type argument must be non-nullable. If the base class is nullable (for example `Base?`), the type argument can be either a nullable or non-nullable reference type. The compiler issues a warning if the type argument is a nullable reference type when the base class is non-nullable. +In a nullable context, the compiler enforces the nullability of the base class type. If the base class is non-nullable (for example `Base`), the type argument must be non-nullable. If the base class is nullable (for example `Base?`), the type argument can be either a nullable or non-nullable reference type. The compiler issues a warning if the type argument is a nullable reference type when the base class is non-nullable. The `where` clause can specify that the type is a `class` or a `struct`. The `struct` constraint removes the need to specify a base class constraint of `System.ValueType`. The `System.ValueType` type can't be used as a base class constraint. The following example shows both the `class` and `struct` constraints: @@ -38,16 +39,16 @@ In a nullable context, the `class` constraint requires a type to be a non-nullab The `where` clause can include the `notnull` constraint. The `notnull` constraint limits the type parameter to non-nullable types. The type can be a [value type](../builtin-types/value-types.md) or a non-nullable reference type. The `notnull` constraint is available for code compiled in a [`nullable enable` context](../../nullable-references.md#nullable-context). Unlike other constraints, if a type argument violates the `notnull` constraint, the compiler generates a warning instead of an error. Warnings are only generated in a `nullable enable` context. -The addition of nullable reference types introduces a potential ambiguity in the meaning of `T?` in generic methods. If `T` is a `struct`, `T?` is the same as . However, if `T` is a reference type, `T?` means that `null` is a valid value. The ambiguity arises because overriding methods can't include constraints. The new `default` constraint resolves this ambiguity. You add it when a base class or interface declares two overloads of a method, one that specifies the `struct` constraint, and one that doesn't have either the `struct` or `class` constraint applied: +The addition of nullable reference types introduces a potential ambiguity in the meaning of `T?` in generic methods. If `T` is a `struct`, `T?` is the same as . However, if `T` is a reference type, `T?` means that `null` is a valid value. The ambiguity arises because overriding methods can't include constraints. The new `default` constraint resolves this ambiguity. Add it when a base class or interface declares two overloads of a method, one that specifies the `struct` constraint, and one that doesn't have either the `struct` or `class` constraint applied: :::code language="csharp" source="snippets/GenericWhereConstraints.cs" ID="BaseClass"::: -You use the `default` constraint to specify that your derived class overrides the method without the constraint in your derived class, or explicit interface implementation. It's only valid on methods that override base methods, or explicit interface implementations: +Use the `default` constraint to specify that your derived class overrides the method without the constraint in your derived class, or explicit interface implementation. It's only valid on methods that override base methods, or explicit interface implementations: :::code language="csharp" source="snippets/GenericWhereConstraints.cs" ID="DerivedClass"::: > [!IMPORTANT] -> Generic declarations that include the `notnull` constraint can be used in a nullable oblivious context, but compiler doesn't enforce the constraint. +> You can use generic declarations that include the `notnull` constraint in a nullable oblivious context, but the compiler doesn't enforce the constraint. :::code language="csharp" source="snippets/GenericWhereConstraints.cs" ID="NotNull"::: @@ -55,7 +56,7 @@ The `where` clause can also include an `unmanaged` constraint. The `unmanaged` c :::code language="csharp" source="snippets/GenericWhereConstraints.cs" ID="Snippet4"::: -The `where` clause can also include a constructor constraint, `new()`. That constraint makes it possible to create an instance of a type parameter using the `new` operator. The [new() Constraint](new-constraint.md) lets the compiler know that any type argument supplied must have an accessible parameterless constructor. For example: +The `where` clause can also include a constructor constraint, `new()`. That constraint makes it possible to create an instance of a type parameter by using the `new` operator. The [new() Constraint](new-constraint.md) lets the compiler know that any type argument supplied must have an accessible parameterless constructor. For example: :::code language="csharp" source="snippets/GenericWhereConstraints.cs" ID="Snippet5"::: @@ -75,7 +76,7 @@ You can also attach constraints to type parameters of generic methods, as shown :::code language="csharp" source="snippets/GenericWhereConstraints.cs" ID="Snippet7"::: -Notice that the syntax to describe type parameter constraints on delegates is the same as that of methods: +The syntax to describe type parameter constraints on delegates is the same as that of methods: :::code language="csharp" source="snippets/GenericWhereConstraints.cs" ID="Snippet8"::: diff --git a/docs/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables.md b/docs/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables.md index 0e011e909526b..00d8be00d5563 100644 --- a/docs/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables.md +++ b/docs/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables.md @@ -81,7 +81,11 @@ You may find that `var` can also be useful with query expressions in which the e The `var` keyword can also be useful when the specific type of the variable is tedious to type on the keyboard, or is obvious, or does not add to the readability of the code. One example where `var` is helpful in this manner is with nested generic types such as those used with group operations. In the following query, the type of the query variable is `IEnumerable>`. As long as you and others who must maintain your code understand this, there is no problem with using implicit typing for convenience and brevity. -[!code-csharp[cscsrefQueryKeywords#13](~/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/Group.cs#13)] +```csharp +var studentQuery = + from student in students + group student by student.Last; +``` The use of `var` helps simplify your code, but its use should be restricted to cases where it is required, or when it makes your code easier to read. For more information about when to use `var` properly, see the [Implicitly typed local variables](../../fundamentals/coding-style/coding-conventions.md#implicitly-typed-local-variables) section on the C# Coding Guidelines article. diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/csquerykeywords.csproj b/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/csquerykeywords.csproj deleted file mode 100644 index c143b009c22e0..0000000000000 --- a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsCsrefQueryKeywords/CS/csquerykeywords.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - Exe - net8.0 - enable - enable - Group.GroupSample2 - - - diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/Project.csproj b/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/Project.csproj deleted file mode 100644 index a22a525793b82..0000000000000 --- a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsContextual/CS/Project.csproj +++ /dev/null @@ -1,7 +0,0 @@ - - - - Library - net8.0 - - diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsLiteral/CS/Project.csproj b/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsLiteral/CS/Project.csproj deleted file mode 100644 index 4ac4d4420a54d..0000000000000 --- a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsLiteral/CS/Project.csproj +++ /dev/null @@ -1,7 +0,0 @@ - - - - Exe - net8.0 - - diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.csproj b/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.csproj deleted file mode 100644 index a265ebbdaeb15..0000000000000 --- a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsModifiers/CS/csrefKeywordsModifiers.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net9.0 - true - csrefKeywordsModifiers.UsingTest - - - diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperator.csproj b/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperator.csproj deleted file mode 100644 index f5a818319b99b..0000000000000 --- a/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsOperator/CS/csrefKeywordsOperator.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - Exe - net48 - csrefKeywordsOperator - csrefKeywordsOperator - KeywordsUberProject.newModifier.DerivedC - - - diff --git a/samples/snippets/csharp/language-reference/keywords/async/wpf/wpf-app1.csproj b/samples/snippets/csharp/language-reference/keywords/async/wpf/wpf-app1.csproj deleted file mode 100644 index 1905e5778c083..0000000000000 --- a/samples/snippets/csharp/language-reference/keywords/async/wpf/wpf-app1.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - WinExe - net48 - true - wpf_app1 - wpf-app1 - - - - - - - diff --git a/samples/snippets/csharp/language-reference/keywords/volatile/volatile.csproj b/samples/snippets/csharp/language-reference/keywords/volatile/volatile.csproj deleted file mode 100644 index af31fefa23aa5..0000000000000 --- a/samples/snippets/csharp/language-reference/keywords/volatile/volatile.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - Exe - net8.0 - enable - - -