diff --git a/docs/csharp/advanced-topics/expression-trees/index.md b/docs/csharp/advanced-topics/expression-trees/index.md
index 35a0cac9c0521..b9e0348d98697 100644
--- a/docs/csharp/advanced-topics/expression-trees/index.md
+++ b/docs/csharp/advanced-topics/expression-trees/index.md
@@ -1,7 +1,7 @@
---
title: "Expression Trees"
description: Learn about expression trees. See how to compile and run code represented by these data structures, where each node is an expression.
-ms.date: 05/29/2024
+ms.date: 10/13/2025
ms.custom: updateeachrelease
---
# Expression Trees
@@ -42,7 +42,7 @@ The C# compiler generates expression trees only from expression lambdas (or sing
There are some newer C# language elements that don't translate well into expression trees. Expression trees can't contain `await` expressions, or `async` lambda expressions. Many of the features added in C# 6 and later don't appear exactly as written in expression trees. Instead, newer features are exposed in expression trees in the equivalent, earlier syntax, where possible. Other constructs aren't available. It means that code that interprets expression trees works the same when new language features are introduced. However, even with these limitations, expression trees do enable you to create dynamic algorithms that rely on interpreting and modifying code that is represented as a data structure. It enables rich libraries such as Entity Framework to accomplish what they do.
-Expression trees won't support new expression node types. It would be a breaking change for all libraries interpreting expression trees to introduce new node types. The following list includes most C# language elements that can't be used:
+Expression trees don't support new expression node types. It would be a breaking change for all libraries interpreting expression trees to introduce new node types. The following list includes most C# language elements that can't be used:
- [Conditional methods](../../language-reference/preprocessor-directives.md#conditional-compilation) removed from the output
- [`base` access](../../language-reference/keywords/base.md)
diff --git a/docs/csharp/asynchronous-programming/task-asynchronous-programming-model.md b/docs/csharp/asynchronous-programming/task-asynchronous-programming-model.md
index f405a684252c6..c1632661d7be7 100644
--- a/docs/csharp/asynchronous-programming/task-asynchronous-programming-model.md
+++ b/docs/csharp/asynchronous-programming/task-asynchronous-programming-model.md
@@ -1,18 +1,18 @@
---
title: The Task Asynchronous Programming (TAP) model with async and await"
description: Learn when and how to use Task-based async programming, a simplified approach to asynchronous programming in C#.
-ms.date: 02/08/2023
+ms.date: 10/13/2025
---
# Task asynchronous programming model
You can avoid performance bottlenecks and enhance the overall responsiveness of your application by using asynchronous programming. However, traditional techniques for writing asynchronous applications can be complicated, making them difficult to write, debug, and maintain.
-C# supports simplified approach, async programming, that leverages asynchronous support in the .NET runtime. The compiler does the difficult work that the developer used to do, and your application retains a logical structure that resembles synchronous code. As a result, you get all the advantages of asynchronous programming with a fraction of the effort.
+C# supports simplified approach, async programming, that uses asynchronous support in the .NET runtime. The compiler does the difficult work that the developer used to do, and your application retains a logical structure that resembles synchronous code. As a result, you get all the advantages of asynchronous programming with a fraction of the effort.
-This topic provides an overview of when and how to use async programming and includes links to support topics that contain details and examples.
+This article provides an overview of when and how to use async programming and includes links to other articles that contain details and examples.
-## Async improves responsiveness
+## Async improves responsiveness
Asynchrony is essential for activities that are potentially blocking, such as web access. Access to a web resource sometimes is slow or delayed. If such an activity is blocked in a synchronous process, the entire application must wait. In an asynchronous process, the application can continue with other work that doesn't depend on the web resource until the potentially blocking task finishes.
@@ -25,13 +25,13 @@ The following table shows typical areas where asynchronous programming improves
| Working with images | | |
| WCF programming | [Synchronous and Asynchronous Operations](../../framework/wcf/synchronous-and-asynchronous-operations.md) | |
-Asynchrony proves especially valuable for applications that access the UI thread because all UI-related activity usually shares one thread. If any process is blocked in a synchronous application, all are blocked. Your application stops responding, and you might conclude that it has failed when instead it's just waiting.
+Asynchrony proves especially valuable for applications that access the UI thread because all UI-related activity usually shares one thread. If any process is blocked in a synchronous application, all are blocked. Your application stops responding, and you might conclude that it failed when instead it's just waiting.
When you use asynchronous methods, the application continues to respond to the UI. You can resize or minimize a window, for example, or you can close the application if you don't want to wait for it to finish.
The async-based approach adds the equivalent of an automatic transmission to the list of options that you can choose from when designing asynchronous operations. That is, you get all the benefits of traditional asynchronous programming but with much less effort from the developer.
-## Async methods are easy to write
+## Async methods are easy to write
The [async](../language-reference/keywords/async.md) and [await](../language-reference/operators/await.md) keywords in C# are the heart of async programming. By using those two keywords, you can use resources in .NET Framework, .NET Core, or the Windows Runtime to create an asynchronous method almost as easily as you create a synchronous method. Asynchronous methods that you define by using the `async` keyword are referred to as *async methods*.
@@ -41,7 +41,7 @@ You can find a complete Windows Presentation Foundation (WPF) example available
:::code language="csharp" source="snippets/access-web/Program.cs" id="ControlFlow":::
-You can learn several practices from the preceding sample. Start with the method signature. It includes the `async` modifier. The return type is `Task` (See "Return Types" section for more options). The method name ends in `Async`. In the body of the method, `GetStringAsync` returns a `Task`. That means that when you `await` the task you'll get a `string` (`contents`). Before awaiting the task, you can do work that doesn't rely on the `string` from `GetStringAsync`.
+You can learn several practices from the preceding sample. Start with the method signature. It includes the `async` modifier. The return type is `Task` (See "Return Types" section for more options). The method name ends in `Async`. In the body of the method, `GetStringAsync` returns a `Task`. That means that when you `await` the task you get a `string` (`contents`). Before awaiting the task, you can do work that doesn't rely on the `string` from `GetStringAsync`.
Pay close attention to the `await` operator. It suspends `GetUrlContentLengthAsync`:
@@ -69,15 +69,15 @@ The following characteristics summarize what makes the previous example an async
- `void` if you're writing an async event handler.
- Any other type that has a `GetAwaiter` method.
- For more information, see the [Return types and parameters](#BKMK_ReturnTypesandParameters) section.
+ For more information, see the [Return types and parameters](#return-types-and-parameters) section.
-- The method usually includes at least one `await` expression, which marks a point where the method can't continue until the awaited asynchronous operation is complete. In the meantime, the method is suspended, and control returns to the method's caller. The next section of this topic illustrates what happens at the suspension point.
+- The method usually includes at least one `await` expression, which marks a point where the method can't continue until the awaited asynchronous operation is complete. In the meantime, the method is suspended, and control returns to the method's caller. The next section of this article illustrates what happens at the suspension point.
In async methods, you use the provided keywords and types to indicate what you want to do, and the compiler does the rest, including keeping track of what must happen when control returns to an await point in a suspended method. Some routine processes, such as loops and exception handling, can be difficult to handle in traditional asynchronous code. In an async method, you write these elements much as you would in a synchronous solution, and the problem is solved.
For more information about asynchrony in previous versions of .NET Framework, see [TPL and traditional .NET Framework asynchronous programming](../../standard/parallel-programming/tpl-and-traditional-async-programming.md).
-## What happens in an async method
+## What happens in an async method
The most important thing to understand in asynchronous programming is how the control flow moves from method to method. The following diagram leads you through the process:
@@ -93,39 +93,39 @@ The numbers in the diagram correspond to the following steps, initiated when a c
`GetStringAsync` returns a , where `TResult` is a string, and `GetUrlContentLengthAsync` assigns the task to the `getStringTask` variable. The task represents the ongoing process for the call to `GetStringAsync`, with a commitment to produce an actual string value when the work is complete.
-1. Because `getStringTask` hasn't been awaited yet, `GetUrlContentLengthAsync` can continue with other work that doesn't depend on the final result from `GetStringAsync`. That work is represented by a call to the synchronous method `DoIndependentWork`.
+1. Because `getStringTask` isn't awaited yet, `GetUrlContentLengthAsync` can continue with other work that doesn't depend on the final result from `GetStringAsync`. That work is represented by a call to the synchronous method `DoIndependentWork`.
1. `DoIndependentWork` is a synchronous method that does its work and returns to its caller.
-1. `GetUrlContentLengthAsync` has run out of work that it can do without a result from `getStringTask`. `GetUrlContentLengthAsync` next wants to calculate and return the length of the downloaded string, but the method can't calculate that value until the method has the string.
+1. `GetUrlContentLengthAsync` runs out of work that it can do without a result from `getStringTask`. `GetUrlContentLengthAsync` next wants to calculate and return the length of the downloaded string, but the method can't calculate that value until the method has the string.
Therefore, `GetUrlContentLengthAsync` uses an await operator to suspend its progress and to yield control to the method that called `GetUrlContentLengthAsync`. `GetUrlContentLengthAsync` returns a `Task` to the caller. The task represents a promise to produce an integer result that's the length of the downloaded string.
> [!NOTE]
- > If `GetStringAsync` (and therefore `getStringTask`) completes before `GetUrlContentLengthAsync` awaits it, control remains in `GetUrlContentLengthAsync`. The expense of suspending and then returning to `GetUrlContentLengthAsync` would be wasted if the called asynchronous process `getStringTask` has already completed and `GetUrlContentLengthAsync` doesn't have to wait for the final result.
+ > If `GetStringAsync` (and therefore `getStringTask`) completes before `GetUrlContentLengthAsync` awaits it, control remains in `GetUrlContentLengthAsync`. The expense of suspending and then returning to `GetUrlContentLengthAsync` would be wasted if the called asynchronous process `getStringTask` is complete and `GetUrlContentLengthAsync` doesn't have to wait for the final result.
Inside the calling method the processing pattern continues. The caller might do other work that doesn't depend on the result from `GetUrlContentLengthAsync` before awaiting that result, or the caller might await immediately. The calling method is waiting for `GetUrlContentLengthAsync`, and `GetUrlContentLengthAsync` is waiting for `GetStringAsync`.
1. `GetStringAsync` completes and produces a string result. The string result isn't returned by the call to `GetStringAsync` in the way that you might expect. (Remember that the method already returned a task in step 3.) Instead, the string result is stored in the task that represents the completion of the method, `getStringTask`. The await operator retrieves the result from `getStringTask`. The assignment statement assigns the retrieved result to `contents`.
-1. When `GetUrlContentLengthAsync` has the string result, the method can calculate the length of the string. Then the work of `GetUrlContentLengthAsync` is also complete, and the waiting event handler can resume. In the full example at the end of the topic, you can confirm that the event handler retrieves and prints the value of the length result.
-If you are new to asynchronous programming, take a minute to consider the difference between synchronous and asynchronous behavior. A synchronous method returns when its work is complete (step 5), but an async method returns a task value when its work is suspended (steps 3 and 6). When the async method eventually completes its work, the task is marked as completed and the result, if any, is stored in the task.
+1. When `GetUrlContentLengthAsync` has the string result, the method can calculate the length of the string. Then the work of `GetUrlContentLengthAsync` is also complete, and the waiting event handler can resume. In the full example at the end of the article, you can confirm that the event handler retrieves and prints the value of the length result.
+If you're new to asynchronous programming, take a minute to consider the difference between synchronous and asynchronous behavior. A synchronous method returns when its work is complete (step 5), but an async method returns a task value when its work is suspended (steps 3 and 6). When the async method eventually completes its work, the task is marked as completed and the result, if any, is stored in the task.
-## API async methods
+## API async methods
-You might be wondering where to find methods such as `GetStringAsync` that support async programming. .NET Framework 4.5 or higher and .NET Core contain many members that work with `async` and `await`. You can recognize them by the "Async" suffix that's appended to the member name, and by their return type of or . For example, the `System.IO.Stream` class contains methods such as , , and alongside the synchronous methods , , and .
+You might be wondering where to find methods such as `GetStringAsync` that support async programming. .NET Framework 4.5 or higher and .NET Core contain many members that work with `async` and `await`. You can recognize them by the "Async" suffix appended to the member name, and by their return type of or . For example, the `System.IO.Stream` class contains methods such as , , and alongside the synchronous methods , , and .
The Windows Runtime also contains many methods that you can use with `async` and `await` in Windows apps. For more information, see [Threading and async programming](/windows/uwp/threading-async/) for UWP development, and [Asynchronous programming (Windows Store apps)](/previous-versions/windows/apps/hh464924(v=win.10)) and [Quickstart: Calling asynchronous APIs in C# or Visual Basic](/previous-versions/windows/apps/hh452713(v=win.10)) if you use earlier versions of the Windows Runtime.
-## Threads
+## Threads
Async methods are intended to be non-blocking operations. An `await` expression in an async method doesn't block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method.
-The `async` and `await` keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available.
+The `async` and `await` keywords don't cause extra threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available.
The async-based approach to asynchronous programming is preferable to existing approaches in almost every case. In particular, this approach is better than the class for I/O-bound operations because the code is simpler and you don't have to guard against race conditions. In combination with the method, async programming is better than for CPU-bound operations because async programming separates the coordination details of running your code from the work that `Task.Run` transfers to the thread pool.
-## async and await
+## Async and await
If you specify that a method is an async method by using the [async](../language-reference/keywords/async.md) modifier, you enable the following two capabilities.
@@ -137,12 +137,12 @@ If you specify that a method is an async method by using the [async](../language
An async method typically contains one or more occurrences of an `await` operator, but the absence of `await` expressions doesn't cause a compiler error. If an async method doesn't use an `await` operator to mark a suspension point, the method executes as a synchronous method does, despite the `async` modifier. The compiler issues a warning for such methods.
-`async` and `await` are contextual keywords. For more information and examples, see the following topics:
+`async` and `await` are contextual keywords. For more information and examples, see the following articles:
- [async](../language-reference/keywords/async.md)
- [await](../language-reference/operators/await.md)
-## Return types and parameters
+## Return types and parameters
An async method typically returns a or a . Inside an async method, an `await` operator is applied to a task that's returned from a call to another async method.
@@ -150,7 +150,7 @@ You specify as the return type if the met
You use as the return type if the method has no return statement or has a return statement that doesn't return an operand.
-You can also specify any other return type, provided that the type includes a `GetAwaiter` method. is an example of such a type. It is available in the [System.Threading.Tasks.Extension](https://www.nuget.org/packages/System.Threading.Tasks.Extensions/) NuGet package.
+You can also specify any other return type, if the type includes a `GetAwaiter` method. is an example of such a type. It's available in the [System.Threading.Tasks.Extension](https://www.nuget.org/packages/System.Threading.Tasks.Extensions/) NuGet package.
The following example shows how you declare and call a method that returns a or a :
@@ -198,13 +198,13 @@ Asynchronous APIs in Windows Runtime programming have one of the following retur
-
-
-## Naming convention
+## Naming convention
-By convention, methods that return commonly awaitable types (for example, `Task`, `Task`, `ValueTask`, `ValueTask`) should have names that end with "Async". Methods that start an asynchronous operation but do not return an awaitable type should not have names that end with "Async", but may start with "Begin", "Start", or some other verb to suggest this method does not return or throw the result of the operation.
+By convention, methods that return commonly awaitable types (for example, `Task`, `Task`, `ValueTask`, `ValueTask`) should have names that end with "Async". Methods that start an asynchronous operation but don't return an awaitable type shouldn't have names that end with "Async", but might start with "Begin", "Start", or some other verb to suggest this method doesn't return or throw the result of the operation.
You can ignore the convention where an event, base class, or interface contract suggests a different name. For example, you shouldn't rename common event handlers, such as `OnButtonClick`.
-## Related articles (Visual Studio)
+## Related articles (Visual Studio)
| Title | Description |
|--|--|
@@ -212,8 +212,8 @@ You can ignore the convention where an event, base class, or interface contract
| [Async return types (C#)](async-return-types.md) | Illustrates the types that async methods can return, and explains when each type is appropriate. |
| Cancel tasks with a cancellation token as a signaling mechanism. | Shows how to add the following functionality to your async solution: - [Cancel a list of tasks (C#)](cancel-an-async-task-or-a-list-of-tasks.md) - [Cancel tasks after a period of time (C#)](cancel-async-tasks-after-a-period-of-time.md) - [Process asynchronous task as they complete (C#)](start-multiple-async-tasks-and-process-them-as-they-complete.md) |
| [Using async for file access (C#)](using-async-for-file-access.md) | Lists and demonstrates the benefits of using async and await to access files. |
-| [Task-based asynchronous pattern (TAP)](../../standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap.md) | Describes an asynchronous pattern, the pattern is based on the and types. |
-| [Async Videos on Channel 9](/shows/browse?terms=async) | Provides links to a variety of videos about async programming. |
+| [Task-based asynchronous pattern (TAP)](../../standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap.md) | Describes an asynchronous pattern. The pattern is based on the and types. |
+| [Async Videos on Channel 9](/shows/browse?terms=async) | Provides links to various videos about async programming. |
## See also
diff --git a/docs/csharp/fundamentals/coding-style/identifier-names.md b/docs/csharp/fundamentals/coding-style/identifier-names.md
index e93bc1ded9ff9..b5dd421dad868 100644
--- a/docs/csharp/fundamentals/coding-style/identifier-names.md
+++ b/docs/csharp/fundamentals/coding-style/identifier-names.md
@@ -1,13 +1,15 @@
---
title: "Identifier names - rules and conventions"
description: "Learn the rules for valid identifier names in the C# programming language. In addition, learn the common naming conventions used by the .NET runtime team and the .NET docs team."
-ms.date: 11/27/2023
+ms.date: 10/10/2025
ai-usage: ai-assisted
---
# C# identifier naming rules and conventions
An **identifier** is the name you assign to a type (class, interface, struct, delegate, or enum), member, variable, or namespace.
+This article covers the essential rules for valid C# identifiers and the naming conventions used to help you write consistent, professional code.
+
## Naming rules
Valid identifiers must follow these rules. The C# compiler produces an error for any identifier that doesn't follow these rules:
@@ -184,15 +186,15 @@ The following guidelines apply to type parameters on generic type parameters. Ty
- **Do** name generic type parameters with descriptive names, unless a single letter name is completely self explanatory and a descriptive name wouldn't add value.
- :::code language="./snippets/coding-conventions" source="./snippets/coding-conventions/Program.cs" id="TypeParametersOne":::
+ :::code language="csharp" source="./snippets/coding-conventions/Program.cs" id="TypeParametersOne":::
- **Consider** using `T` as the type parameter name for types with one single letter type parameter.
- :::code language="./snippets/coding-conventions" source="./snippets/coding-conventions/Program.cs" id="TypeParametersTwo":::
+ :::code language="csharp" source="./snippets/coding-conventions/Program.cs" id="TypeParametersTwo":::
- **Do** prefix descriptive type parameter names with "T".
- :::code language="./snippets/coding-conventions" source="./snippets/coding-conventions/Program.cs" id="TypeParametersThree":::
+ :::code language="csharp" source="./snippets/coding-conventions/Program.cs" id="TypeParametersThree":::
- **Consider** indicating constraints placed on a type parameter in the name of parameter. For example, a parameter constrained to `ISession` might be called `TSession`.
diff --git a/docs/csharp/fundamentals/object-oriented/inheritance.md b/docs/csharp/fundamentals/object-oriented/inheritance.md
index 89e8dce56f25f..f6b833e6ce4b1 100644
--- a/docs/csharp/fundamentals/object-oriented/inheritance.md
+++ b/docs/csharp/fundamentals/object-oriented/inheritance.md
@@ -16,15 +16,15 @@ ms.assetid: 81d64ee4-50f9-4d6c-a8dc-257c348d2eea
Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics of object-oriented programming. Inheritance enables you to create new classes that reuse, extend, and modify the behavior defined in other classes. The class whose members are inherited is called the *base class*, and the class that inherits those members is called the *derived class*. A derived class can have only one direct base class. However, inheritance is transitive. If `ClassC` is derived from `ClassB`, and `ClassB` is derived from `ClassA`, `ClassC` inherits the members declared in `ClassB` and `ClassA`.
> [!NOTE]
-> Structs do not support inheritance, but they can implement interfaces.
+> Structs don't support inheritance, but they can implement interfaces.
Conceptually, a derived class is a specialization of the base class. For example, if you have a base class `Animal`, you might have one derived class that is named `Mammal` and another derived class that is named `Reptile`. A `Mammal` is an `Animal`, and a `Reptile` is an `Animal`, but each derived class represents different specializations of the base class.
-Interface declarations may define a default implementation for its members. These implementations are inherited by derived interfaces, and by classes that implement those interfaces. For more information on default interface methods, see the article on [interfaces](../types/interfaces.md).
+Interface declarations can define a default implementation for its members. These implementations are inherited by derived interfaces, and by classes that implement those interfaces. For more information on default interface methods, see the article on [interfaces](../types/interfaces.md).
When you define a class to derive from another class, the derived class implicitly gains all the members of the base class, except for its constructors and finalizers. The derived class reuses the code in the base class without having to reimplement it. You can add more members in the derived class. The derived class extends the functionality of the base class.
-The following illustration shows a class `WorkItem` that represents an item of work in some business process. Like all classes, it derives from and inherits all its methods. `WorkItem` adds six members of its own. These members include a constructor, because constructors aren't inherited. Class `ChangeRequest` inherits from `WorkItem` and represents a particular kind of work item. `ChangeRequest` adds two more members to the members that it inherits from `WorkItem` and from . It must add its own constructor, and it also adds `originalItemID`. Property `originalItemID` enables the `ChangeRequest` instance to be associated with the original `WorkItem` to which the change request applies.
+The following illustration shows a class `WorkItem` that represents an item of work in some business process. Like all classes, it derives from and inherits all its methods. `WorkItem` adds six members of its own. These members include a constructor, because constructors aren't inherited. Class `ChangeRequest` inherits from `WorkItem` and represents a particular type of work item. `ChangeRequest` adds two more members to the members that it inherits from `WorkItem` and from . It must add its own constructor, and it also adds `originalItemID`. Property `originalItemID` enables the `ChangeRequest` instance to be associated with the original `WorkItem` to which the change request applies.

@@ -46,7 +46,7 @@ You can declare a class as [abstract](../../language-reference/keywords/abstract
## Interfaces
-An *interface* is a reference type that defines a set of members. All classes and structs that implement that interface must implement that set of members. An interface may define a default implementation for any or all of these members. A class can implement multiple interfaces even though it can derive from only a single direct base class.
+An *interface* is a reference type that defines a set of members. All classes and structs that implement that interface must implement that set of members. An interface might define a default implementation for any or all of these members. A class can implement multiple interfaces even though it can derive from only a single direct base class.
Interfaces are used to define specific capabilities for classes that don't necessarily have an "is a" relationship. For example, the interface can be implemented by any class or struct to determine whether two objects of the type are equivalent (however the type defines equivalence). doesn't imply the same kind of "is a" relationship that exists between a base class and a derived class (for example, a `Mammal` is an `Animal`). For more information, see [Interfaces](../types/interfaces.md).
@@ -56,4 +56,4 @@ A class can prevent other classes from inheriting from it, or from any of its me
## Derived class hiding of base class members
-A derived class can hide base class members by declaring members with the same name and signature. The [`new`](../../language-reference/keywords/new-modifier.md) modifier can be used to explicitly indicate that the member isn't intended to be an override of the base member. The use of [`new`](../../language-reference/keywords/new-modifier.md) isn't required, but a compiler warning will be generated if [`new`](../../language-reference/keywords/new-modifier.md) isn't used. For more information, 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).
+A derived class can hide base class members by declaring members with the same name and signature. The [`new`](../../language-reference/keywords/new-modifier.md) modifier can be used to explicitly indicate that the member isn't intended to be an override of the base member. The use of [`new`](../../language-reference/keywords/new-modifier.md) isn't required, but a compiler warning is generated if [`new`](../../language-reference/keywords/new-modifier.md) isn't used. For more information, 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).
diff --git a/docs/csharp/fundamentals/object-oriented/objects.md b/docs/csharp/fundamentals/object-oriented/objects.md
index 9f003e0893984..b53f1a5ec8a18 100644
--- a/docs/csharp/fundamentals/object-oriented/objects.md
+++ b/docs/csharp/fundamentals/object-oriented/objects.md
@@ -1,14 +1,14 @@
---
title: "Objects - create instances of types"
description: C# uses a class or struct definition to define types of objects. In an object-oriented language such as C#, a program consists of objects interacting dynamically.
-ms.date: 05/14/2021
+ms.date: 10/13/2025
helpviewer_keywords:
- "objects [C#], about objects"
- "variables [C#]"
---
# Objects - create instances of types
-A class or struct definition is like a blueprint that specifies what the type can do. An object is basically a block of memory that has been allocated and configured according to the blueprint. A program may create many objects of the same class. Objects are also called instances, and they can be stored in either a named variable or in an array or collection. Client code is the code that uses these variables to call the methods and access the public properties of the object. In an object-oriented language such as C#, a typical program consists of multiple objects interacting dynamically.
+A class or struct definition is like a blueprint that specifies what the type can do. An object is basically a block of memory that is allocated and configured according to the blueprint. A program might create many objects of the same class. Objects are also called instances, and they can be stored in either a named variable or in an array or collection. Client code is the code that uses these variables to call the methods and access the public properties of the object. In an object-oriented language such as C#, a typical program consists of multiple objects interacting dynamically.
> [!NOTE]
> Static types behave differently than what is described here. For more information, see [Static Classes and Static Class Members](../../programming-guide/classes-and-structs/static-classes-and-static-class-members.md).
@@ -25,10 +25,10 @@ Because structs are value types, a variable of a struct object holds a copy of t
:::code language="csharp" source="./snippets/objects/Application.cs" interactive="try-dotnet":::
-The memory for both `p1` and `p2` is allocated on the thread stack. That memory is reclaimed along with the type or method in which it's declared. This is one reason why structs are copied on assignment. By contrast, the memory that is allocated for a class instance is automatically reclaimed (garbage collected) by the common language runtime when all references to the object have gone out of scope. It isn't possible to deterministically destroy a class object like you can in C++. For more information about garbage collection in .NET, see [Garbage Collection](../../../standard/garbage-collection/index.md).
+The memory for both `p1` and `p2` is allocated on the thread stack. That memory is reclaimed along with the type or method in which it's declared. This is one reason why structs are copied on assignment. By contrast, the memory that is allocated for a class instance is automatically reclaimed (garbage collected) by the common language runtime when all references to the object are out of scope. It isn't possible to deterministically destroy a class object like you can in C++. For more information about garbage collection in .NET, see [Garbage Collection](../../../standard/garbage-collection/index.md).
> [!NOTE]
-> The allocation and deallocation of memory on the managed heap is highly optimized in the common language runtime. In most cases there is no significant difference in the performance cost of allocating a class instance on the heap versus allocating a struct instance on the stack.
+> The allocation and deallocation of memory on the managed heap is highly optimized in the common language runtime. In most cases, there's no significant difference in the performance cost of allocating a class instance on the heap versus allocating a struct instance on the stack.
## Object Identity vs. Value Equality
@@ -39,7 +39,7 @@ When you compare two objects for equality, you must first distinguish whether yo
:::code language="csharp" source="./snippets/objects/Equality.cs" ID="Snippet32":::
- The default implementation of `Equals` uses boxing and reflection in some cases. For information about how to provide an efficient equality algorithm that is specific to your type, see [How to define value equality for a type](../../programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type.md). Records are reference types that use value semantics for equality.
+ The default implementation of `Equals` uses boxing and reflection in some cases. For information about how to provide an efficient equality algorithm that's specific to your type, see [How to define value equality for a type](../../programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type.md). Records are reference types that use value semantics for equality.
- To determine whether the values of the fields in two class instances are equal, you might be able to use the method or the [== operator](../../language-reference/operators/equality-operators.md#equality-operator-). However, only use them if the class has overridden or overloaded them to provide a custom definition of what "equality" means for objects of that type. The class might also implement the interface or the interface. Both interfaces provide methods that can be used to test value equality. When designing your own classes that override `Equals`, make sure to follow the guidelines stated in [How to define value equality for a type](../../programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type.md) and .
diff --git a/docs/csharp/fundamentals/object-oriented/polymorphism.md b/docs/csharp/fundamentals/object-oriented/polymorphism.md
index f62506825e912..38b932d808f58 100644
--- a/docs/csharp/fundamentals/object-oriented/polymorphism.md
+++ b/docs/csharp/fundamentals/object-oriented/polymorphism.md
@@ -1,7 +1,7 @@
---
title: "Polymorphism"
description: Learn about polymorphism, a key concept in object-oriented programming languages like C#, which describes the relationship between base and derived classes.
-ms.date: 05/14/2021
+ms.date: 10/13/2025
helpviewer_keywords:
- "C# language, polymorphism"
- "polymorphism [C#]"
@@ -10,8 +10,8 @@ helpviewer_keywords:
Polymorphism is often referred to as the third pillar of object-oriented programming, after encapsulation and inheritance. Polymorphism is a Greek word that means "many-shaped" and it has two distinct aspects:
-- At run time, objects of a derived class may be treated as objects of a base class in places such as method parameters and collections or arrays. When this polymorphism occurs, the object's declared type is no longer identical to its run-time type.
-- Base classes may define and implement [virtual](../../language-reference/keywords/virtual.md) *methods*, and derived classes can [override](../../language-reference/keywords/override.md) them, which means they provide their own definition and implementation. At run-time, when client code calls the method, the CLR looks up the run-time type of the object, and invokes that override of the virtual method. In your source code you can call a method on a base class, and cause a derived class's version of the method to be executed.
+- At run time, objects of a derived class can be treated as objects of a base class in places such as method parameters and collections or arrays. When this polymorphism occurs, the object's declared type is no longer identical to its run-time type.
+- Base classes might define and implement [virtual](../../language-reference/keywords/virtual.md) *methods*, and derived classes can [override](../../language-reference/keywords/override.md) them, which means they provide their own definition and implementation. At run-time, when client code calls the method, the CLR looks up the run-time type of the object, and invokes that override of the virtual method. In your source code you can call a method on a base class, and cause a derived class's version of the method to be executed.
Virtual methods enable you to work with groups of related objects in a uniform way. For example, suppose you have a drawing application that enables a user to create various kinds of shapes on a drawing surface. You don't know at compile time which specific types of shapes the user will create. However, the application has to keep track of all the various types of shapes that are created, and it has to update them in response to user mouse actions. You can use polymorphism to solve this problem in two basic steps:
@@ -32,11 +32,11 @@ In C#, every type is polymorphic because all types, including user-defined types
### Virtual members
-When a derived class inherits from a base class, it includes all the members of the base class. All the behavior declared in the base class is part of the derived class. That enables objects of the derived class to be treated as objects of the base class. Access modifiers (`public`, `protected`, `private` and so on) determine if those members are accessible from the derived class implementation. Virtual methods gives the designer different choices for the behavior of the derived class:
+When a derived class inherits from a base class, it includes all the members of the base class. All the behavior declared in the base class is part of the derived class. That enables objects of the derived class to be treated as objects of the base class. Access modifiers (`public`, `protected`, `private`, and so on) determine if those members are accessible from the derived class implementation. Virtual methods give the designer different choices for the behavior of the derived class:
-- The derived class may override virtual members in the base class, defining new behavior.
-- The derived class may inherit the closest base class method without overriding it, preserving the existing behavior but enabling further derived classes to override the method.
-- The derived class may define new non-virtual implementation of those members that hide the base class implementations.
+- The derived class can override virtual members in the base class, defining new behavior.
+- The derived class can inherit the closest base class method without overriding it, preserving the existing behavior but enabling further derived classes to override the method.
+- The derived class can define new non-virtual implementation of those members that hide the base class implementations.
A derived class can override a base class member only if the base class member is declared as [virtual](../../language-reference/keywords/virtual.md) or [abstract](../../language-reference/keywords/abstract.md). The derived member must use the [override](../../language-reference/keywords/override.md) keyword to explicitly indicate that the method is intended to participate in virtual invocation. The following code provides an example:
@@ -50,7 +50,7 @@ Virtual methods and properties enable derived classes to extend a base class wit
### Hide base class members with new members
-If you want your derived class to have a member with the same name as a member in a base class, you can use the [new](../../language-reference/keywords/new-modifier.md) keyword to hide the base class member. The `new` keyword is put before the return type of a class member that is being replaced. The following code provides an example:
+If you want your derived class to have a member with the same name as a member in a base class, you can use the [new](../../language-reference/keywords/new-modifier.md) keyword to hide the base class member. The `new` keyword is put before the return type of a class member that's being replaced. The following code provides an example:
:::code language="csharp" source="./snippets/inheritance/Inheritance.cs" ID="SnippetNewMethods":::
@@ -64,7 +64,7 @@ In this example, both variables refer to the same object instance, but the metho
### Prevent derived classes from overriding virtual members
-Virtual members remain virtual, regardless of how many classes have been declared between the virtual member and the class that originally declared it. If class `A` declares a virtual member, and class `B` derives from `A`, and class `C` derives from `B`, class `C` inherits the virtual member, and may override it, regardless of whether class `B` declared an override for that member. The following code provides an example:
+Virtual members remain virtual, regardless of how many classes are declared between the virtual member and the class that originally declared it. If class `A` declares a virtual member, and class `B` derives from `A`, and class `C` derives from `B`, class `C` inherits the virtual member, and might override it, regardless of whether class `B` declared an override for that member. The following code provides an example:
:::code language="csharp" source="./snippets/inheritance/Hierarchy.cs" ID="SnippetFirstHierarchy":::
@@ -76,11 +76,11 @@ In the previous example, the method `DoWork` is no longer virtual to any class d
:::code language="csharp" source="./snippets/inheritance/Hierarchy.cs" ID="SnippetNewDeclaration":::
-In this case, if `DoWork` is called on `D` using a variable of type `D`, the new `DoWork` is called. If a variable of type `C`, `B`, or `A` is used to access an instance of `D`, a call to `DoWork` will follow the rules of virtual inheritance, routing those calls to the implementation of `DoWork` on class `C`.
+In this case, if `DoWork` is called on `D` using a variable of type `D`, the new `DoWork` is called. If a variable of type `C`, `B`, or `A` is used to access an instance of `D`, a call to `DoWork` follows the rules of virtual inheritance, routing those calls to the implementation of `DoWork` on class `C`.
### Access base class virtual members from derived classes
-A derived class that has replaced or overridden a method or property can still access the method or property on the base class using the `base` keyword. The following code provides an example:
+A derived class that replaces or overrides a method or property can still access the method or property on the base class using the `base` keyword. The following code provides an example:
```csharp
public class Base
@@ -102,4 +102,4 @@ public class Derived : Base
For more information, see [base](../../language-reference/keywords/base.md).
> [!NOTE]
-> It is recommended that virtual members use `base` to call the base class implementation of that member in their own implementation. Letting the base class behavior occur enables the derived class to concentrate on implementing behavior specific to the derived class. If the base class implementation is not called, it is up to the derived class to make their behavior compatible with the behavior of the base class.
+> It's recommended that virtual members use `base` to call the base class implementation of that member in their own implementation. Letting the base class behavior occur enables the derived class to concentrate on implementing behavior specific to the derived class. If the base class implementation isn't called, it's up to the derived class to make their behavior compatible with the behavior of the base class.
diff --git a/docs/csharp/fundamentals/object-oriented/snippets/inheritance/Inheritance.cs b/docs/csharp/fundamentals/object-oriented/snippets/inheritance/Inheritance.cs
index 1e1e08970ef4d..67ebbde974977 100644
--- a/docs/csharp/fundamentals/object-oriented/snippets/inheritance/Inheritance.cs
+++ b/docs/csharp/fundamentals/object-oriented/snippets/inheritance/Inheritance.cs
@@ -28,10 +28,10 @@ public WorkItem()
// Instance constructor that has three parameters.
public WorkItem(string title, string desc, TimeSpan joblen)
{
- this.ID = GetNextID();
- this.Title = title;
- this.Description = desc;
- this.jobLength = joblen;
+ ID = GetNextID();
+ Title = title;
+ Description = desc;
+ jobLength = joblen;
}
// Static constructor to initialize the static member, currentID. This
@@ -93,10 +93,10 @@ public ChangeRequest(string title, string desc, TimeSpan jobLen,
public class Shape
{
// A few example members
- public int X { get; private set; }
- public int Y { get; private set; }
- public int Height { get; set; }
- public int Width { get; set; }
+ public int X { get; init; }
+ public int Y { get; init; }
+ public int Height { get; init; }
+ public int Width { get; init; }
// Virtual method
public virtual void Draw()
@@ -143,12 +143,12 @@ public static void Example()
// can all be used wherever a Shape is expected. No cast is
// required because an implicit conversion exists from a derived
// class to its base class.
- var shapes = new List
- {
+ List shapes =
+ [
new Rectangle(),
new Triangle(),
new Circle()
- };
+ ];
// Polymorphism at work #2: the virtual method Draw is
// invoked on each of the derived classes, not the base class.
@@ -170,7 +170,7 @@ Performing base class drawing tasks
public static void VirtualExamples()
{
//
- DerivedClass B = new DerivedClass();
+ DerivedClass B = new();
B.DoWork(); // Calls the new method.
BaseClass A = B;
@@ -183,10 +183,7 @@ public static void VirtualExamples()
public class BaseClass
{
public virtual void DoWork() { }
- public virtual int WorkProperty
- {
- get { return 0; }
- }
+ public virtual int WorkProperty => 0;
}
public class DerivedClass : BaseClass
{
@@ -227,7 +224,7 @@ public static class NewMethods
public static void Example()
{
//
- DerivedClass B = new DerivedClass();
+ DerivedClass B = new();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
diff --git a/docs/csharp/fundamentals/object-oriented/snippets/inheritance/Program.cs b/docs/csharp/fundamentals/object-oriented/snippets/inheritance/Program.cs
index 42790a2a18a6b..043b887af6009 100644
--- a/docs/csharp/fundamentals/object-oriented/snippets/inheritance/Program.cs
+++ b/docs/csharp/fundamentals/object-oriented/snippets/inheritance/Program.cs
@@ -7,16 +7,16 @@ static void Main(string[] args)
//
// Create an instance of WorkItem by using the constructor in the
// base class that takes three arguments.
- WorkItem item = new WorkItem("Fix Bugs",
- "Fix all bugs in my code branch",
- new TimeSpan(3, 4, 0, 0));
+ WorkItem item = new("Fix Bugs",
+ "Fix all bugs in my code branch",
+ new TimeSpan(3, 4, 0, 0));
// Create an instance of ChangeRequest by using the constructor in
// the derived class that takes four arguments.
- ChangeRequest change = new ChangeRequest("Change Base Class Design",
- "Add members to the class",
- new TimeSpan(4, 0, 0),
- 1);
+ ChangeRequest change = new("Change Base Class Design",
+ "Add members to the class",
+ new TimeSpan(4, 0, 0),
+ 1);
// Use the ToString method defined in WorkItem.
Console.WriteLine(item.ToString());
diff --git a/docs/csharp/fundamentals/object-oriented/snippets/objects/Application.cs b/docs/csharp/fundamentals/object-oriented/snippets/objects/Application.cs
index 35382d189fc94..f92d48c2a7363 100644
--- a/docs/csharp/fundamentals/object-oriented/snippets/objects/Application.cs
+++ b/docs/csharp/fundamentals/object-oriented/snippets/objects/Application.cs
@@ -19,7 +19,7 @@ static void Main()
{
// Create struct instance and initialize by using "new".
// Memory is allocated on thread stack.
- Person p1 = new Person("Alex", 9);
+ Person p1 = new("Alex", 9);
Console.WriteLine($"p1 Name = {p1.Name} Age = {p1.Age}");
// Create new struct object. Note that struct can be initialized
diff --git a/docs/csharp/fundamentals/object-oriented/snippets/objects/Equality.cs b/docs/csharp/fundamentals/object-oriented/snippets/objects/Equality.cs
index d11e663baa495..de3be1e869706 100644
--- a/docs/csharp/fundamentals/object-oriented/snippets/objects/Equality.cs
+++ b/docs/csharp/fundamentals/object-oriented/snippets/objects/Equality.cs
@@ -7,19 +7,14 @@ public static void EqualityTest()
//
// Person is defined in the previous example.
- //public struct Person
+ //public struct Person(string name, int age)
//{
- // public string Name;
- // public int Age;
- // public Person(string name, int age)
- // {
- // Name = name;
- // Age = age;
- // }
+ // public string Name { get; set; } = name;
+ // public int Age { get; set; } = age;
//}
- Person p1 = new Person("Wallace", 75);
- Person p2 = new Person("", 42);
+ Person p1 = new("Wallace", 75);
+ Person p2 = new("", 42);
p2.Name = "Wallace";
p2.Age = 75;
diff --git a/docs/csharp/fundamentals/object-oriented/snippets/objects/Program.cs b/docs/csharp/fundamentals/object-oriented/snippets/objects/Program.cs
index 3853079e5da10..cfba6e9dc4ece 100644
--- a/docs/csharp/fundamentals/object-oriented/snippets/objects/Program.cs
+++ b/docs/csharp/fundamentals/object-oriented/snippets/objects/Program.cs
@@ -1,14 +1,9 @@
using System;
-public class Person
+public class Person(string name, int age)
{
- public string Name { get; set; }
- public int Age { get; set; }
- public Person(string name, int age)
- {
- Name = name;
- Age = age;
- }
+ public string Name { get; set; } = name;
+ public int Age { get; set; } = age;
// Other properties, methods, events...
}
@@ -16,7 +11,7 @@ class Program
{
static void Main()
{
- Person person1 = new Person("Leopold", 6);
+ Person person1 = new("Leopold", 6);
Console.WriteLine($"person1 Name = {person1.Name} Age = {person1.Age}");
// Declare new person, assign person1 to it.
@@ -28,11 +23,12 @@ static void Main()
Console.WriteLine($"person2 Name = {person2.Name} Age = {person2.Age}");
Console.WriteLine($"person1 Name = {person1.Name} Age = {person1.Age}");
+
+ /*
+ Output:
+ person1 Name = Leopold Age = 6
+ person2 Name = Molly Age = 16
+ person1 Name = Molly Age = 16
+ */
}
}
-/*
- Output:
- person1 Name = Leopold Age = 6
- person2 Name = Molly Age = 16
- person1 Name = Molly Age = 16
-*/
diff --git a/docs/csharp/fundamentals/tutorials/oop.md b/docs/csharp/fundamentals/tutorials/oop.md
index e4fc84c0758cf..acf3d0e5397ab 100644
--- a/docs/csharp/fundamentals/tutorials/oop.md
+++ b/docs/csharp/fundamentals/tutorials/oop.md
@@ -83,7 +83,7 @@ The `GiftCardAccount` class needs two changes to implement its month-end functio
:::code language="csharp" source="./snippets/object-oriented-programming/GiftCardAccount.cs" ID="GiftCardAccountConstruction":::
-The constructor provides a default value for the `monthlyDeposit` value so callers can omit a `0` for no monthly deposit. Next, override the `PerformMonthEndTransactions` method to add the monthly deposit, if it was set to a non-zero value in the constructor:
+The constructor provides a default value for the `monthlyDeposit` value so callers can omit a `0` for no monthly deposit. Next, override the `PerformMonthEndTransactions` method to add the monthly deposit, if it was set to a nonzero value in the constructor:
:::code language="csharp" source="./snippets/object-oriented-programming/GiftCardAccount.cs" ID="AddMonthlyDeposit":::
diff --git a/docs/csharp/fundamentals/tutorials/snippets/object-oriented-programming/BankAccount.cs b/docs/csharp/fundamentals/tutorials/snippets/object-oriented-programming/BankAccount.cs
index 04956ec3c9d33..24a8f72c74ad3 100644
--- a/docs/csharp/fundamentals/tutorials/snippets/object-oriented-programming/BankAccount.cs
+++ b/docs/csharp/fundamentals/tutorials/snippets/object-oriented-programming/BankAccount.cs
@@ -37,14 +37,11 @@ public BankAccount(string name, decimal initialBalance, decimal minimumBalance)
}
//
- private readonly List _allTransactions = new();
+ private readonly List _allTransactions = [];
public void MakeDeposit(decimal amount, DateTime date, string note)
{
- if (amount <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(amount), "Amount of deposit must be positive");
- }
+ ArgumentOutOfRangeException.ThrowIfNegativeOrZero(amount);
var deposit = new Transaction(amount, date, note);
_allTransactions.Add(deposit);
}
@@ -52,10 +49,7 @@ public void MakeDeposit(decimal amount, DateTime date, string note)
//
public void MakeWithdrawal(decimal amount, DateTime date, string note)
{
- if (amount <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
- }
+ ArgumentOutOfRangeException.ThrowIfNegativeOrZero(amount);
Transaction? overdraftTransaction = CheckWithdrawalLimit(Balance - amount < _minimumBalance);
Transaction? withdrawal = new(-amount, date, note);
_allTransactions.Add(withdrawal);
diff --git a/docs/csharp/fundamentals/types/anonymous-types.md b/docs/csharp/fundamentals/types/anonymous-types.md
index e8a619819a6dc..851dd8dda8d57 100644
--- a/docs/csharp/fundamentals/types/anonymous-types.md
+++ b/docs/csharp/fundamentals/types/anonymous-types.md
@@ -1,7 +1,7 @@
---
title: "Anonymous Types"
description: Anonymous types in C# encapsulate a set of read-only properties in an object without having to explicitly define a type. The compiler generates a name.
-ms.date: 05/14/2021
+ms.date: 10/13/2025
f1_keywords:
- "anonymousObject_CSharpKeyword"
helpviewer_keywords:
@@ -10,7 +10,7 @@ helpviewer_keywords:
---
# Anonymous types
-Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. The type name is generated by the compiler and is not available at the source code level. The type of each property is inferred by the compiler.
+Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. The type name is generated by the compiler and isn't available at the source code level. The type of each property is inferred by the compiler.
You create anonymous types by using the [`new`](../../language-reference/operators/new-operator.md) operator together with an object initializer. For more information about object initializers, see [Object and Collection Initializers](../../programming-guide/classes-and-structs/object-and-collection-initializers.md).
@@ -26,9 +26,9 @@ Console.WriteLine(v.Amount + v.Message);
Anonymous types are typically used in the [`select`](../../language-reference/keywords/select-clause.md) clause of a query expression to return a subset of the properties from each object in the source sequence. For more information about queries, see [LINQ in C#](../../linq/index.md).
-Anonymous types contain one or more public read-only properties. No other kinds of class members, such as methods or events, are valid. The expression that is used to initialize a property cannot be `null`, an anonymous function, or a pointer type.
+Anonymous types contain one or more public read-only properties. No other kinds of class members, such as methods or events, are valid. The expression that is used to initialize a property can't be `null`, an anonymous function, or a pointer type.
-The most common scenario is to initialize an anonymous type with properties from another type. In the following example, assume that a class exists that is named `Product`. Class `Product` includes `Color` and `Price` properties, together with other properties that you are not interested in:
+The most common scenario is to initialize an anonymous type with properties from another type. In the following example, assume that a class exists that is named `Product`. Class `Product` includes `Color` and `Price` properties, together with other properties that you aren't interested in:
:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="ProductDefinition":::
@@ -44,7 +44,7 @@ Anonymous types support *projection initializers*, which allow you to use local
:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="ProjectionInitializers":::
-This simplified syntax is particularly useful when creating anonymous types with many properties:
+This simplified syntax is useful when creating anonymous types with many properties:
:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="ProjectionExample":::
@@ -58,11 +58,11 @@ In these cases, you must explicitly specify the member name.
> [!TIP]
> You can use .NET style rule [IDE0037](../../../fundamentals/code-analysis/style-rules/ide0037.md) to enforce whether inferred or explicit member names are preferred.
-It is also possible to define a field by object of another type: class, struct or even another anonymous type. It is done by using the variable holding this object just like in the following example, where two anonymous types are created using already instantiated user-defined types. In both cases the `product` field in the anonymous type `shipment` and `shipmentWithBonus` will be of type `Product` containing its default values of each field. And the `bonus` field will be of anonymous type created by the compiler.
+It's also possible to define a field by object of another type: class, struct, or even another anonymous type. It's done by using the variable holding this object just like in the following example, where two anonymous types are created using already instantiated user-defined types. In both cases, the `product` field in the anonymous type `shipment` and `shipmentWithBonus` is of type `Product` containing its default values of each field. And the `bonus` field is of anonymous type created by the compiler.
:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="snippet03":::
-Typically, when you use an anonymous type to initialize a variable, you declare the variable as an implicitly typed local variable by using [var](../../language-reference/statements/declarations.md#implicitly-typed-local-variables). The type name cannot be specified in the variable declaration because only the compiler has access to the underlying name of the anonymous type. For more information about `var`, see [Implicitly Typed Local Variables](../../programming-guide/classes-and-structs/implicitly-typed-local-variables.md).
+Typically, when you use an anonymous type to initialize a variable, you declare the variable as an implicitly typed local variable by using [var](../../language-reference/statements/declarations.md#implicitly-typed-local-variables). The type name can't be specified in the variable declaration because only the compiler has access to the underlying name of the anonymous type. For more information about `var`, see [Implicitly Typed Local Variables](../../programming-guide/classes-and-structs/implicitly-typed-local-variables.md).
You can create an array of anonymously typed elements by combining an implicitly typed local variable and an implicitly typed array, as shown in the following example.
@@ -70,7 +70,7 @@ You can create an array of anonymously typed elements by combining an implicitly
var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};
```
-Anonymous types are [`class`](../../language-reference/keywords/class.md) types that derive directly from [`object`](../../language-reference/builtin-types/reference-types.md), and that cannot be cast to any type except [`object`](../../language-reference/builtin-types/reference-types.md). The compiler provides a name for each anonymous type, although your application cannot access it. From the perspective of the common language runtime, an anonymous type is no different from any other reference type.
+Anonymous types are [`class`](../../language-reference/keywords/class.md) types that derive directly from [`object`](../../language-reference/builtin-types/reference-types.md), and that can't be cast to any type except [`object`](../../language-reference/builtin-types/reference-types.md). The compiler provides a name for each anonymous type, although your application can't access it. From the perspective of the common language runtime, an anonymous type is no different from any other reference type.
If two or more anonymous object initializers in an assembly specify a sequence of properties that are in the same order and that have the same names and types, the compiler treats the objects as instances of the same type. They share the same compiler-generated type information.
@@ -78,12 +78,12 @@ Anonymous types support non-destructive mutation in the form of [with expression
:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="snippet02":::
-You cannot declare a field, a property, an event, or the return type of a method as having an anonymous type. Similarly, you cannot declare a formal parameter of a method, property, constructor, or indexer as having an anonymous type. To pass an anonymous type, or a collection that contains anonymous types, as an argument to a method, you can declare the parameter as type `object`. However, using `object` for anonymous types defeats the purpose of strong typing. If you must store query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type.
+You can't declare a field, a property, an event, or the return type of a method as having an anonymous type. Similarly, you can't declare a formal parameter of a method, property, constructor, or indexer as having an anonymous type. To pass an anonymous type, or a collection that contains anonymous types, as an argument to a method, you can declare the parameter as type `object`. However, using `object` for anonymous types defeats the purpose of strong typing. If you must store query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type.
Because the and methods on anonymous types are defined in terms of the `Equals` and `GetHashCode` methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.
> [!NOTE]
-> The [accessibility level](../../programming-guide/classes-and-structs/access-modifiers.md) of an anonymous type is `internal`, hence two anonymous types defined in different assemblies are not of the same type.
+> The [accessibility level](../../programming-guide/classes-and-structs/access-modifiers.md) of an anonymous type is `internal`. Hence, two anonymous types defined in different assemblies aren't of the same type.
> Therefore instances of anonymous types can't be equal to each other when defined in different assemblies, even when having all their properties equal.
Anonymous types do override the method, concatenating the name and `ToString` output of every property surrounded by curly braces.
diff --git a/docs/csharp/fundamentals/types/classes.md b/docs/csharp/fundamentals/types/classes.md
index 32f51ac17f7cb..67a764635fa97 100644
--- a/docs/csharp/fundamentals/types/classes.md
+++ b/docs/csharp/fundamentals/types/classes.md
@@ -1,7 +1,7 @@
---
title: "Classes in the C# type system."
description: Learn about class types, how to use classes, and how to create new class type declarations for your app.
-ms.date: 08/15/2024
+ms.date: 10/10/2025
helpviewer_keywords:
- "classes [C#]"
- "C# language, classes"
@@ -13,14 +13,14 @@ helpviewer_keywords:
A type that is defined as a [`class`](../../language-reference/keywords/class.md) is a *reference type*. At run time, when you declare a variable of a reference type, the variable contains the value [`null`](../../language-reference/keywords/null.md) until you explicitly create an instance of the class by using the [`new`](../../language-reference/operators/new-operator.md) operator, or assign it an object of a compatible type created elsewhere, as shown in the following example:
```csharp
-//Declaring an object of type MyClass.
+// Declaring an object of type MyClass.
MyClass mc = new MyClass();
-//Declaring another object of the same type, assigning it the value of the first object.
+// Declaring another object of the same type, assigning it the value of the first object.
MyClass mc2 = mc;
```
-When the object is created, enough memory is allocated on the managed heap for that specific object, and the variable holds only a reference to the location of said object. The memory used by an object is reclaimed by the automatic memory management functionality of the CLR, which is known as *garbage collection*. For more information about garbage collection, see [Automatic memory management and garbage collection](../../../standard/garbage-collection/fundamentals.md).
+When the object is created, enough memory is allocated on the managed heap for that specific object, and the variable holds only a reference to the location of said object. The memory used by an object is reclaimed by the automatic memory management functionality of the Common Language Runtime (CLR), which is known as *garbage collection*. For more information about garbage collection, see [Automatic memory management and garbage collection](../../../standard/garbage-collection/fundamentals.md).
## Declaring classes
diff --git a/docs/csharp/fundamentals/types/generics.md b/docs/csharp/fundamentals/types/generics.md
index 020db9863af1a..f3842db7619a5 100644
--- a/docs/csharp/fundamentals/types/generics.md
+++ b/docs/csharp/fundamentals/types/generics.md
@@ -1,7 +1,7 @@
---
title: "Generic classes and methods"
description: Learn about generics. Generic types maximize code reuse, type safety, and performance, and are commonly used to create collection classes.
-ms.date: 03/14/2024
+ms.date: 10/10/2025
f1_keywords:
- "generics_CSharpKeyword"
helpviewer_keywords:
diff --git a/docs/csharp/fundamentals/types/index.md b/docs/csharp/fundamentals/types/index.md
index 47b6991810d3e..381a615c2adb3 100644
--- a/docs/csharp/fundamentals/types/index.md
+++ b/docs/csharp/fundamentals/types/index.md
@@ -1,7 +1,7 @@
---
title: "Learn the fundamentals of the C# type system"
description: Learn about creating types in C#, such as tuples, records, value types, and reference types. Learn to choose between these options.
-ms.date: 08/15/2024
+ms.date: 10/10/2025
helpviewer_keywords:
- "value types [C#]"
- "reference types [C#]"
@@ -30,7 +30,7 @@ The compiler uses type information to make sure all operations that are performe
:::code language="csharp" source="../../programming-guide/types/snippets/index/Program.cs" ID="TypeSafeExample":::
> [!NOTE]
-> C and C++ developers, notice that in C#, `bool` is not convertible to `int`.
+> C and C++ developers, notice that in C#, `bool` isn't convertible to `int`.
The compiler embeds the type information into the executable file as metadata. The common language runtime (CLR) uses that metadata at run time to further guarantee type safety when it allocates and reclaims memory.
@@ -78,7 +78,7 @@ The following illustration shows the relationship between value types and refere

> [!NOTE]
-> You can see that the most commonly used types are all organized in the namespace. However, the namespace in which a type is contained has no relation to whether it is a value type or reference type.
+> You can see that the most commonly used types are all organized in the namespace. However, the namespace in which a type is contained has no relation to whether it's a value type or reference type.
Classes and structs are two of the basic constructs of the common type system in .NET. Each is essentially a data structure that encapsulates a set of data and behaviors that belong together as a logical unit. The data and behaviors are the *members* of the class, struct, or record. The members include its methods, properties, events, and so on, as listed later in this article.
@@ -90,7 +90,7 @@ A struct is a value type. When a struct is created, the variable to which the st
Record types can be either reference types (`record class`) or value types (`record struct`). Record types contain methods that support value-equality.
-In general, classes are used to model more complex behavior. Classes typically store data that is intended to be modified after a class object is created. Structs are best suited for small data structures. Structs typically store data that isn't intended to be modified after the struct is created. Record types are data structures with additional compiler synthesized members. Records typically store data that isn't intended to be modified after the object is created.
+In general, classes are used to model more complex behavior. Classes typically store data that is intended to be modified after a class object is created. Structs are best suited for small data structures. Structs typically store data that isn't intended to be modified after the struct is created. Record types are data structures with extra compiler synthesized members. Records typically store data that isn't intended to be modified after the object is created.
### Value types
diff --git a/docs/csharp/fundamentals/types/interfaces.md b/docs/csharp/fundamentals/types/interfaces.md
index 1e971ddc8b432..7228c8a09faec 100644
--- a/docs/csharp/fundamentals/types/interfaces.md
+++ b/docs/csharp/fundamentals/types/interfaces.md
@@ -1,14 +1,14 @@
---
title: "Interfaces - define behavior for multiple types"
description: An interface in C# contains definitions for a group of related functionalities that a non-abstract class or a struct must implement. It specifies the members and their signatures for a type that implements the interface.
-ms.date: 05/14/2021
+ms.date: 10/13/2025
helpviewer_keywords:
- "interfaces [C#]"
- "C# language, interfaces"
---
# Interfaces - define behavior for multiple types
-An interface contains definitions for a group of related functionalities that a non-abstract [`class`](../../language-reference/keywords/class.md) or a [`struct`](../../language-reference/builtin-types/struct.md) must implement. An interface may define `static` methods, which must have an implementation. An interface may define a default implementation for members. An interface may not declare instance data such as fields, automatically implemented properties, or property-like events.
+An interface contains definitions for a group of related functionalities that a non-abstract [`class`](../../language-reference/keywords/class.md) or a [`struct`](../../language-reference/builtin-types/struct.md) must implement. An interface can define `static` methods. An interface can define a default implementation for members. An interface can't declare instance data such as fields, automatically implemented properties, or property-like events.
By using interfaces, you can, for example, include behavior from multiple sources in a class. That capability is important in C# because the language doesn't support multiple inheritance of classes. In addition, you must use an interface if you want to simulate inheritance for structs, because they can't actually inherit from another struct or class.
@@ -24,14 +24,14 @@ The definition of `IEquatable` doesn't provide an implementation for `Equals`
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).
-Interfaces can contain instance methods, properties, events, indexers, or any combination of those four member types. Interfaces may contain static constructors, fields, constants, or operators. Beginning with C# 11, interface members that aren't fields may be `static abstract`. An interface can't contain instance fields, instance constructors, or finalizers. Interface members are public by default, and you can explicitly specify accessibility modifiers, such as `public`, `protected`, `internal`, `private`, `protected internal`, or `private protected`. A `private` member must have a default implementation.
+Interfaces can contain instance methods, properties, events, indexers, or any combination of those four member types. Interfaces can contain static constructors, fields, constants, or operators. Beginning with C# 11, interface members that aren't fields can be `static abstract`. An interface can't contain instance fields, instance constructors, or finalizers. Interface members are public by default, and you can explicitly specify accessibility modifiers, such as `public`, `protected`, `internal`, `private`, `protected internal`, or `private protected`. A `private` member must have a default implementation.
To implement an interface member using implicit implementation, the corresponding member of the implementing class must be public, non-static, and have the same name and signature as the interface member. However, when an interface is meant to be internal only or uses internal types in its signature, you can use explicit interface implementation instead, which doesn't require the implementing member to be public.
> [!NOTE]
-> When an interface declares static members, a type implementing that interface may also declare static members with the same signature. Those are distinct and uniquely identified by the type declaring the member. The static member declared in a type *doesn't* override the static member declared in the interface.
+> When an interface declares static members, a type implementing that interface might also declare static members with the same signature. Those are distinct and uniquely identified by the type declaring the member. The static member declared in a type *doesn't* override the static member declared in the interface.
-A class or struct that implements an interface must provide an implementation for all declared members without a default implementation provided by the interface. However, if a base class implements an interface, any class that's derived from the base class inherits that implementation.
+A class or struct that implements an interface must provide an implementation for all declared members without a default implementation provided by the interface. However, if a base class implements an interface, any class derived from the base class inherits that implementation.
The following example shows an implementation of the interface. The implementing class, `Car`, must provide an implementation of the method.
@@ -39,7 +39,7 @@ The following example shows an implementation of the
class Product
{
- public string? Color {get;set;}
- public decimal Price {get;set;}
- public string? Name {get;set;}
- public string? Category {get;set;}
- public string? Size {get;set;}
+ public string? Color { get; set; }
+ public decimal Price { get; set; }
+ public string? Name { get; set; }
+ public string? Category { get; set; }
+ public string? Size { get; set; }
}
//
class Anonymous
@@ -21,10 +21,10 @@ static void Main()
// Don't show this unless you add a bunch more
// properties to the type. Otherwise it obviates the
// need for the anonymous type.
- List products = new ()
- {
- new Product() { Color="Orange", Price=2.00M},
- };
+ List products =
+ [
+ new Product { Color = "Orange", Price = 2.00M }
+ ];
//
var productQuery =
@@ -54,12 +54,12 @@ from prod in products
//
// Explicit member names.
var personExplicit = new { FirstName = "Kyle", LastName = "Mit" };
-
+
// Projection initializers (inferred member names).
var firstName = "Kyle";
var lastName = "Mit";
var personInferred = new { firstName, lastName };
-
+
// Both create equivalent anonymous types with the same property names.
Console.WriteLine($"Explicit: {personExplicit.FirstName} {personExplicit.LastName}");
Console.WriteLine($"Inferred: {personInferred.firstName} {personInferred.lastName}");
@@ -69,13 +69,13 @@ from prod in products
var title = "Software Engineer";
var department = "Engineering";
var salary = 75000;
-
+
// Using projection initializers.
var employee = new { title, department, salary };
-
+
// Equivalent to explicit syntax:
// var employee = new { title = title, department = department, salary = salary };
-
+
Console.WriteLine($"Title: {employee.title}, Department: {employee.department}, Salary: {employee.salary}");
//
}
diff --git a/docs/csharp/fundamentals/types/snippets/classes/Program.cs b/docs/csharp/fundamentals/types/snippets/classes/Program.cs
index 8ad6131e85b3e..c56fe653fc561 100644
--- a/docs/csharp/fundamentals/types/snippets/classes/Program.cs
+++ b/docs/csharp/fundamentals/types/snippets/classes/Program.cs
@@ -1,6 +1,5 @@
-
-//
-Customer object1 = new Customer();
+//
+Customer object1 = new();
//
//
@@ -9,14 +8,14 @@
//
-Customer object3 = new Customer();
+Customer object3 = new();
Customer object4 = object3;
//
/*
var p1 = new Person(); // Error! Required properties not set
*/
-var p2 = new Person() {FirstName = "Grace", LastName = "Hopper" };
+var p2 = new Person { FirstName = "Grace", LastName = "Hopper" };
//
//[access modifier] - [class] - [identifier]
diff --git a/docs/csharp/programming-guide/classes-and-structs/access-modifiers.md b/docs/csharp/programming-guide/classes-and-structs/access-modifiers.md
index ed954559d7883..de8f7d54f7936 100644
--- a/docs/csharp/programming-guide/classes-and-structs/access-modifiers.md
+++ b/docs/csharp/programming-guide/classes-and-structs/access-modifiers.md
@@ -1,7 +1,7 @@
---
title: "Access Modifiers"
description: All types and type members in C# have an accessibility level that controls whether they can be used from other code. Review this list of access modifiers.
-ms.date: 08/20/2024
+ms.date: 10/10/2025
helpviewer_keywords:
- "C# Language, access modifiers"
- "access modifiers [C#], about"
@@ -41,7 +41,7 @@ Multiple declarations of a [partial class or partial member](./partial-classes-a
## Class and struct accessibility
-Classes and structs declared directly within a namespace (aren't nested within other classes or structs) can have `public`, `internal` or `file` access. `internal` is the default if no access modifier is specified.
+Classes and structs declared directly within a namespace (aren't nested within other classes or structs) can have `public`, `internal`, or `file` access. `internal` is the default if no access modifier is specified.
Struct members, including nested classes and structs, can be declared `public`, `internal`, or `private`. Class members, including nested classes and structs, can be `public`, `protected internal`, `protected`, `internal`, `private protected`, or `private`. Class and struct members, including nested classes and structs, have `private` access by default.
diff --git a/docs/csharp/programming-guide/classes-and-structs/named-and-optional-arguments.md b/docs/csharp/programming-guide/classes-and-structs/named-and-optional-arguments.md
index 9316a2dc5187e..12a18d0101d1e 100644
--- a/docs/csharp/programming-guide/classes-and-structs/named-and-optional-arguments.md
+++ b/docs/csharp/programming-guide/classes-and-structs/named-and-optional-arguments.md
@@ -1,7 +1,7 @@
---
title: "Named and Optional Arguments"
description: Named arguments in C# specify arguments by name, not position. Optional arguments can be omitted.
-ms.date: 03/14/2024
+ms.date: 10/10/2025
f1_keywords:
- "namedParameter_CSharpKeyword"
- "optionalParameter_CSharpKeyword"
@@ -26,7 +26,7 @@ Named and optional parameters enable you to supply arguments for selected parame
## Named arguments
-Named arguments free you from matching the order of arguments to the order of parameters in the parameter lists of called methods. The argument for each parameter can be specified by parameter name. For example, a function that prints order details (such as seller name, order number, and product name) can be called by sending arguments by position, in the order defined by the function.
+Named arguments free you from matching the order of arguments to the order of parameters in the parameter lists of called methods. The argument for each parameter is specified by parameter name. For example, a function that prints order details (such as seller name, order number, and product name) is called by sending arguments by position, in the order defined by the function.
```csharp
PrintOrderDetails("Gift Shop", 31, "Red Mug");
@@ -39,7 +39,7 @@ PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop")
PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);
```
-Named arguments also improve the readability of your code by identifying what each argument represents. In the example method below, the `sellerName` can't be null or white space. As both `sellerName` and `productName` are string types, instead of sending arguments by position, it makes sense to use named arguments to disambiguate the two and reduce confusion for anyone reading the code.
+Named arguments also improve the readability of your code by identifying what each argument represents. In the following example method, the `sellerName` can't be null or white space. As both `sellerName` and `productName` are string types, instead of sending arguments by position, it makes sense to use named arguments to disambiguate the two and reduce confusion for anyone reading the code.
Named arguments, when used with positional arguments, are valid as long as
@@ -49,7 +49,7 @@ Named arguments, when used with positional arguments, are valid as long as
PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");
```
-- they're used in the correct position. In the example below, the parameter `orderNum` is in the correct position but isn't explicitly named.
+- they're used in the correct position. In the following example, the parameter `orderNum` is in the correct position but isn't explicitly named.
```csharp
PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug");
@@ -64,13 +64,13 @@ PrintOrderDetails(productName: "Red Mug", 31, "Gift Shop");
### Example
-The following code implements the examples from this section along with some additional ones.
+The following code implements the examples from this section along with some extra ones.
:::code language="csharp" source="./snippets/NamedAndOptional/program.cs" id="Snippet1":::
## Optional arguments
-The definition of a method, constructor, indexer, or delegate can specify its parameters are required or optional. Any call must provide arguments for all required parameters, but can omit arguments for optional parameters. A nullable reference type (`T?`) allows arguments to be explicitly `null` but does not inherently make a parameter optional.
+The definition of a method, constructor, indexer, or delegate can specify its parameters are required or optional. Any call must provide arguments for all required parameters, but can omit arguments for optional parameters. A nullable reference type (`T?`) allows arguments to be explicitly `null` but doesn't inherently make a parameter optional.
Each optional parameter has a default value as part of its definition. If no argument is sent for that parameter, the default value is used. A default value must be one of the following types of expressions:
@@ -78,7 +78,7 @@ Each optional parameter has a default value as part of its definition. If no arg
- an expression of the form `new ValType()`, where `ValType` is a value type, such as an [enum](../../language-reference/builtin-types/enum.md) or a [struct](../../language-reference/builtin-types/struct.md);
- an expression of the form [default(ValType)](../../language-reference/operators/default.md), where `ValType` is a value type.
-Optional parameters are defined at the end of the parameter list, after any required parameters. The caller must provide arguments for all required parameters and any optional parameters preceding those it specifies. Comma-separated gaps in the argument list aren't supported.For example, in the following code, instance method `ExampleMethod` is defined with one required and two optional parameters.
+Optional parameters are defined at the end of the parameter list, after any required parameters. The caller must provide arguments for all required parameters and any optional parameters preceding those it specifies. Comma-separated gaps in the argument list aren't supported. For example, in the following code, instance method `ExampleMethod` is defined with one required and two optional parameters.
:::code language="csharp" source="./snippets/NamedAndOptional/optional.cs" id="Snippet15":::
@@ -99,7 +99,7 @@ IntelliSense uses brackets to indicate optional parameters, as shown in the foll

> [!NOTE]
-> You can also declare optional parameters by using the .NET class. `OptionalAttribute` parameters do not require a default value. However, if a default value is desired, take a look at class.
+> You can also declare optional parameters by using the .NET class. `OptionalAttribute` parameters don't require a default value. However, if a default value is desired, take a look at class.
### Example
@@ -113,7 +113,7 @@ The preceding code illustrates several cases where optional parameters are used
[Caller information attributes](../../language-reference/attributes/caller-information.md), such as , , , and , are used to obtain information about the caller to a method. These attributes are especially useful when you're debugging or when you need to log information about method calls.
-These attributes are optional parameters with default values provided by the compiler. The caller should not explicitly provide a value for these parameters.
+These attributes are optional parameters with default values provided by the compiler. The caller shouldn't explicitly provide a value for these parameters.
## COM interfaces
diff --git a/docs/csharp/programming-guide/classes-and-structs/object-and-collection-initializers.md b/docs/csharp/programming-guide/classes-and-structs/object-and-collection-initializers.md
index 6b86a1001474f..ed0b8890f3cb8 100644
--- a/docs/csharp/programming-guide/classes-and-structs/object-and-collection-initializers.md
+++ b/docs/csharp/programming-guide/classes-and-structs/object-and-collection-initializers.md
@@ -1,7 +1,7 @@
---
title: "Object and Collection Initializers"
description: Object initializers in C# assign values to accessible fields or properties of an object at creation after invoking a constructor.
-ms.date: 05/17/2024
+ms.date: 10/13/2025
helpviewer_keywords:
- "object initializers [C#]"
- "collection initializers [C#]"
@@ -19,7 +19,7 @@ Object initializers let you assign values to any accessible fields or properties
The object initializers syntax allows you to create an instance, and after that it assigns the newly created object, with its assigned properties, to the variable in the assignment.
-Starting with nested object properties, you can use object initializer syntax without the `new` keyword. This syntax, `Property = { ... }`, allows you to initialize members of existing nested objects, which is particularly useful with read-only properties. For more details, see [Object Initializers with class-typed properties](#object-initializers-with-class-typed-properties).
+Starting with nested object properties, you can use object initializer syntax without the `new` keyword. This syntax, `Property = { ... }`, allows you to initialize members of existing nested objects, which is useful with read-only properties. For more information, see [Object Initializers with class-typed properties](#object-initializers-with-class-typed-properties).
Object initializers can set indexers, in addition to assigning fields and properties. Consider this basic `Matrix` class:
@@ -54,7 +54,7 @@ public string this[char c, int i] { set { ... }; }
## Object Initializers with anonymous types
-Although object initializers can be used in any context, they're especially useful in LINQ query expressions. Query expressions make frequent use of [anonymous types](../../fundamentals/types/anonymous-types.md), which can only be initialized by using an object initializer, as shown in the following declaration.
+Although object initializers can be used in any context, they're especially useful in Language-Integrated Query (LINQ) expressions. Query expressions make frequent use of [anonymous types](../../fundamentals/types/anonymous-types.md), which can only be initialized by using an object initializer, as shown in the following declaration.
```csharp
var pet = new { Age = 10, Name = "Fluffy" };
@@ -139,13 +139,13 @@ These syntaxes behave differently. The following example demonstrates both appro
- **Without `new` keyword** (`ClassB = { BI = 100003 }`): This syntax modifies the existing instance of the property that was created during object construction. It calls member initializers on the existing object.
-- **With `new` keyword** (`ClassB = new() { BI = 100003 }`): This syntax creates a completely new instance and assigns it to the property, replacing any existing instance.
+- **With `new` keyword** (`ClassB = new() { BI = 100003 }`): This syntax creates a new instance and assigns it to the property, replacing any existing instance.
-The initializer without `new` reuses the current instance. In the example above, ClassB's values are: `100003` (new value assigned), `true` (kept from EmbeddedClassTypeA's initialization), `BBBabc` (unchanged default from EmbeddedClassTypeB).
+The initializer without `new` reuses the current instance. In the previous example, ClassB's values are: `100003` (new value assigned), `true` (kept from EmbeddedClassTypeA's initialization), `BBBabc` (unchanged default from EmbeddedClassTypeB).
### Object initializers without `new` for read-only properties
-The syntax without `new` is particularly useful with read-only properties, where you can't assign a new instance but can still initialize the existing instance's members:
+The syntax without `new` is useful with read-only properties, where you can't assign a new instance but can still initialize the existing instance's members:
:::code language="csharp" source="./snippets/object-collection-initializers/ObjectInitializerWithoutNew.cs" id="ReadOnlyPropertyExample":::
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/app.config b/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/app.config
deleted file mode 100644
index 3e0e37cfc8c7a..0000000000000
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/app.config
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/namedandoptionalsnippets.csproj b/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/namedandoptionalsnippets.csproj
index ae9dcbfe6c5a7..05ebaeab7a292 100644
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/namedandoptionalsnippets.csproj
+++ b/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/namedandoptionalsnippets.csproj
@@ -1,94 +1,16 @@
-
-
+
+
- Debug
- AnyCPU
- 10.0.20319
- 2.0
- {595F32EC-B330-4DA1-9D79-9E5E1EA6DDAB}
Exe
- Properties
- NamedAndOptionalSnippets
- NamedAndOptionalSnippets
- v4.8
- 512
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- false
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- false
-
-
+ net8.0
+ enable
+ enable
OptionalNamespace.OptionalExample
+
-
-
-
-
-
-
-
-
-
-
- {2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}
- 2
- 8
- 0
- primary
- False
- True
-
-
- {00020813-0000-0000-C000-000000000046}
- 1
- 9
- 0
- primary
- False
- True
-
-
- {00020905-0000-0000-C000-000000000046}
- 8
- 7
- 0
- primary
- False
- True
-
-
- {0002E157-0000-0000-C000-000000000046}
- 5
- 3
- 0
- primary
- False
- True
-
+
+
-
-
+
\ No newline at end of file
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/properties/assemblyinfo.cs b/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/properties/assemblyinfo.cs
deleted file mode 100644
index 08d25b77fa98c..0000000000000
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/NamedAndOptional/properties/assemblyinfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("NamedAndOptionalSnippets")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Microsoft Corp.")]
-[assembly: AssemblyProduct("NamedAndOptionalSnippets")]
-[assembly: AssemblyCopyright("Copyright © Microsoft Corp. 2009")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("6803107a-bd5f-4a70-834b-0988088f89bb")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/object-collection-initializers/BasicObjectInitializers.cs b/docs/csharp/programming-guide/classes-and-structs/snippets/object-collection-initializers/BasicObjectInitializers.cs
index 51b5b2f63701c..cacb69c078b23 100644
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/object-collection-initializers/BasicObjectInitializers.cs
+++ b/docs/csharp/programming-guide/classes-and-structs/snippets/object-collection-initializers/BasicObjectInitializers.cs
@@ -1,5 +1,4 @@
-
-namespace object_collection_initializers;
+namespace object_collection_initializers;
public class BasicObjectInitializers
{
@@ -81,12 +80,12 @@ from p in products
//
//
- List cats = new List
- {
- new Cat{ Name = "Sylvester", Age=8 },
- new Cat{ Name = "Whiskers", Age=2 },
- new Cat{ Name = "Sasha", Age=14 }
- };
+ List cats =
+ [
+ new Cat { Name = "Sylvester", Age = 8 },
+ new Cat { Name = "Whiskers", Age = 2 },
+ new Cat { Name = "Sasha", Age = 14 }
+ ];
//
//
@@ -176,12 +175,12 @@ public static void Main()
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Cat sameCat = new Cat("Fluffy"){ Age = 10 };
- List cats = new List
- {
+ List cats =
+ [
new Cat { Name = "Sylvester", Age = 8 },
new Cat { Name = "Whiskers", Age = 2 },
new Cat { Name = "Sasha", Age = 14 }
- };
+ ];
List moreCats = new List
{
@@ -222,7 +221,7 @@ public class FullExample
{
class FormattedAddresses : IEnumerable
{
- private List internalList = new List();
+ private List internalList = new();
public IEnumerator GetEnumerator() => internalList.GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => internalList.GetEnumerator();
@@ -292,7 +291,7 @@ public void Add(TKey key, IEnumerable values)
{
if (!internalDictionary.TryGetValue(key, out List? storedValues))
{
- internalDictionary.Add(key, storedValues = new List());
+ internalDictionary.Add(key, storedValues = new());
}
storedValues.AddRange(values);
}
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/static-classes-and-static-class-members/Program.cs b/docs/csharp/programming-guide/classes-and-structs/snippets/static-classes-and-static-class-members/Program.cs
index 92ca7636bdfcc..483f8abc8fa18 100644
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/static-classes-and-static-class-members/Program.cs
+++ b/docs/csharp/programming-guide/classes-and-structs/snippets/static-classes-and-static-class-members/Program.cs
@@ -1,27 +1,11 @@
//
public static class TemperatureConverter
{
- public static double CelsiusToFahrenheit(string temperatureCelsius)
- {
- // Convert argument to double for calculations.
- double celsius = Double.Parse(temperatureCelsius);
-
- // Convert Celsius to Fahrenheit.
- double fahrenheit = (celsius * 9 / 5) + 32;
-
- return fahrenheit;
- }
-
- public static double FahrenheitToCelsius(string temperatureFahrenheit)
- {
- // Convert argument to double for calculations.
- double fahrenheit = Double.Parse(temperatureFahrenheit);
+ public static double CelsiusToFahrenheit(string temperatureCelsius) =>
+ double.Parse(temperatureCelsius) * 9 / 5 + 32;
- // Convert Fahrenheit to Celsius.
- double celsius = (fahrenheit - 32) * 5 / 9;
-
- return celsius;
- }
+ public static double FahrenheitToCelsius(string temperatureFahrenheit) =>
+ (double.Parse(temperatureFahrenheit) - 32) * 5 / 9;
}
class TestTemperatureConverter
@@ -34,20 +18,19 @@ static void Main()
Console.Write(":");
string? selection = Console.ReadLine();
- double F, C = 0;
switch (selection)
{
case "1":
Console.Write("Please enter the Celsius temperature: ");
- F = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine() ?? "0");
- Console.WriteLine($"Temperature in Fahrenheit: {F:F2}");
+ var f = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine() ?? "0");
+ Console.WriteLine($"Temperature in Fahrenheit: {f:F2}");
break;
case "2":
Console.Write("Please enter the Fahrenheit temperature: ");
- C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine() ?? "0");
- Console.WriteLine($"Temperature in Celsius: {C:F2}");
+ var c = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine() ?? "0");
+ Console.WriteLine($"Temperature in Celsius: {c:F2}");
break;
default:
@@ -78,13 +61,7 @@ public class Automobile
{
public static int NumberOfWheels = 4;
- public static int SizeOfGasTank
- {
- get
- {
- return 15;
- }
- }
+ public static int SizeOfGasTank => 15;
public static void Drive() { }
@@ -100,7 +77,7 @@ void Test()
{
//
Automobile.Drive();
- int i = Automobile.NumberOfWheels;
+ var i = Automobile.NumberOfWheels;
//
}
}
diff --git a/docs/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members.md b/docs/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members.md
index f898e3e72b42b..d0678cf53c8bf 100644
--- a/docs/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members.md
+++ b/docs/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members.md
@@ -1,7 +1,7 @@
---
title: "Static Classes and Static Class Members"
description: Static classes can't be instantiated in C#. You access the members of a static class by using the class name itself.
-ms.date: 03/15/2024
+ms.date: 10/13/2025
helpviewer_keywords:
- "C# language, static members"
- "static members [C#]"
@@ -18,7 +18,7 @@ A [static](../../language-reference/keywords/static.md) class is basically the s
UtilityClass.MethodA();
```
- A static class can be used as a convenient container for sets of methods that just operate on input parameters and don't have to get or set any internal instance fields. For example, in the .NET Class Library, the static class contains methods that perform mathematical operations, without any requirement to store or retrieve data that is unique to a particular instance of the class. That is, you apply the members of the class by specifying the class name and the method name, as shown in the following example.
+ A static class can be used as a convenient container for sets of methods that just operate on input parameters and don't have to get or set any internal instance fields. For example, in the .NET Class Library, the static class contains methods that perform mathematical operations, without any requirement to store or retrieve data that's unique to a particular instance of the class. That is, you apply the members of the class by specifying the class name and the method name, as shown in the following example.
```csharp
double dub = -3.14;
diff --git a/docs/csharp/programming-guide/concepts/index.md b/docs/csharp/programming-guide/concepts/index.md
index 2d8f7f3a981d4..30e0d01a9f9e0 100644
--- a/docs/csharp/programming-guide/concepts/index.md
+++ b/docs/csharp/programming-guide/concepts/index.md
@@ -1,7 +1,7 @@
---
title: "Programming Concepts"
description: Use the resources in this section to understand programming concepts in the C# language, including object-oriented programming.
-ms.date: 04/22/2024
+ms.date: 10/10/2025
---
# Programming concepts (C#)
diff --git a/docs/csharp/programming-guide/generics/constraints-on-type-parameters.md b/docs/csharp/programming-guide/generics/constraints-on-type-parameters.md
index 57336cebcb272..0adad6ba44ade 100644
--- a/docs/csharp/programming-guide/generics/constraints-on-type-parameters.md
+++ b/docs/csharp/programming-guide/generics/constraints-on-type-parameters.md
@@ -1,7 +1,7 @@
---
title: "Constraints on type parameters"
description: Learn about constraints on type parameters. Constraints tell the compiler what capabilities a type argument must have.
-ms.date: 07/26/2024
+ms.date: 10/10/2025
f1_keywords:
- "defaultconstraint_CSharpKeyword"
- "notnull_CSharpKeyword"
@@ -117,7 +117,7 @@ The `unmanaged` constraint implies the `struct` constraint and can't be combined
## Delegate constraints
-You can use or as a base class constraint. The CLR always allowed this constraint, but the C# language disallowed it. The `System.Delegate` constraint enables you to write code that works with delegates in a type-safe manner. The following code defines an extension method that combines two delegates provided they're the same type:
+You can use or as a base class constraint. The Common Language Runtime (CLR) always allowed this constraint, but the C# language disallowed it. The `System.Delegate` constraint enables you to write code that works with delegates in a type-safe manner. The following code defines an extension method that combines two delegates provided they're the same type:
:::code language="csharp" source="./snippets/GenericWhereConstraints.cs" id="Snippet16":::
diff --git a/docs/csharp/programming-guide/generics/snippets/GenericWhereConstraints.cs b/docs/csharp/programming-guide/generics/snippets/GenericWhereConstraints.cs
index a2b9c907e1b7f..06d9d7ce50141 100644
--- a/docs/csharp/programming-guide/generics/snippets/GenericWhereConstraints.cs
+++ b/docs/csharp/programming-guide/generics/snippets/GenericWhereConstraints.cs
@@ -6,7 +6,7 @@ namespace Generics
public class AGenericClass where T : IComparable { }
//
- //
+ //
public class UsingEnum where T : System.Enum { }
public class UsingDelegate where T : System.Delegate { }
@@ -28,19 +28,16 @@ class UnManagedWrapper
//
//
-#nullable enable
class NotNullContainer
where T : notnull
{
}
-#nullable restore
//
//
public class MyGenericClass where T : IComparable, new()
{
- // The following line is not possible without new() constraint:
- T item = new T();
+ T item = new();
}
//
@@ -90,7 +87,7 @@ private class Node
public void AddHead(T t)
{
- Node n = new Node(t) { Next = head };
+ Node n = new(t) { Next = head };
head = n;
}
@@ -98,7 +95,7 @@ public IEnumerator GetEnumerator()
{
Node? current = head;
- while (current != null)
+ while (current is not null)
{
yield return current.Data;
current = current.Next;
@@ -108,22 +105,20 @@ public IEnumerator GetEnumerator()
public T? FindFirstOccurrence(string s)
{
Node? current = head;
- T? t = null;
- while (current != null)
+ while (current is not null)
{
//The constraint enables access to the Name property.
if (current.Data.Name == s)
{
- t = current.Data;
- break;
+ return current.Data;
}
else
{
current = current.Next;
}
}
- return t;
+ return null;
}
}
//
@@ -135,11 +130,9 @@ public interface IEmployee
//
class EmployeeList where T : notnull, Employee, IComparable, new()
{
- // ...
public void AddDefault()
{
- T t = new T();
- // ...
+ T t = new();
}
}
//
@@ -173,8 +166,8 @@ public static class UnmanagedExtensions
unsafe public static byte[] ToByteArray(this T argument) where T : unmanaged
{
var size = sizeof(T);
- var result = new Byte[size];
- Byte* p = (byte*)&argument;
+ var result = new byte[size];
+ byte* p = (byte*)&argument;
for (var i = 0; i < size; i++)
result[i] = *p++;
return result;
@@ -212,15 +205,15 @@ public static void Examples()
//
public static void OpEqualsTest(T s, T t) where T : class
{
- System.Console.WriteLine(s == t);
+ Console.WriteLine(s == t);
}
private static void TestStringEquality()
{
string s1 = "target";
- System.Text.StringBuilder sb = new System.Text.StringBuilder("target");
+ System.Text.StringBuilder sb = new("target");
string s2 = sb.ToString();
- OpEqualsTest(s1, s2);
+ OpEqualsTest(s1, s2);
}
//
@@ -232,7 +225,7 @@ public struct Point3D
}
private static void TestUnmanaged()
{
- var thing = new Point3D { X = 1, Y = 2, Z = 3 };
+ Point3D thing = new() { X = 1, Y = 2, Z = 3 };
var storage = thing.ToByteArray();
@@ -276,7 +269,6 @@ private static void TestEnumValues()
foreach (var pair in map)
Console.WriteLine($"{pair.Key}:\t{pair.Value}");
-
//
}
}
diff --git a/docs/csharp/programming-guide/types/boxing-and-unboxing.md b/docs/csharp/programming-guide/types/boxing-and-unboxing.md
index 444cfa262d5c1..daff88a52b229 100644
--- a/docs/csharp/programming-guide/types/boxing-and-unboxing.md
+++ b/docs/csharp/programming-guide/types/boxing-and-unboxing.md
@@ -1,7 +1,7 @@
---
title: "Boxing and Unboxing"
-description: Learn about boxing and unboxing in C# programming. See code examples and view additional available resources.
-ms.date: 07/20/2015
+description: Learn about boxing and unboxing in C# programming. See code examples and view other available resources.
+ms.date: 10/13/2025
f1_keywords:
- "cs.boxing"
helpviewer_keywords:
@@ -61,7 +61,7 @@ This example converts an integer variable `i` to an object `o` by using boxing.
Unboxing is an explicit conversion from the type `object` to a [value type](../../language-reference/builtin-types/value-types.md) or from an interface type to a value type that implements the interface. An unboxing operation consists of:
-- Checking the object instance to make sure that it is a boxed value of the given value type.
+- Checking the object instance to make sure that it's a boxed value of the given value type.
- Copying the value from the instance into the value-type variable.
@@ -91,13 +91,13 @@ If you change the statement:
int j = (short)o;
```
-to:
+To:
```csharp
int j = (int)o;
```
-the conversion will be performed, and you will get the output:
+The conversion is performed, and you'll get the output:
`Unboxing OK.`
diff --git a/docs/csharp/programming-guide/types/snippets/index/Program.cs b/docs/csharp/programming-guide/types/snippets/index/Program.cs
index 47021bd1e0fa5..648300797b168 100644
--- a/docs/csharp/programming-guide/types/snippets/index/Program.cs
+++ b/docs/csharp/programming-guide/types/snippets/index/Program.cs
@@ -22,15 +22,10 @@ public string GetName(int ID)
}
//
-public struct Coords
+public struct Coords(int x, int y)
{
- public int x, y;
-
- public Coords(int p1, int p2)
- {
- x = p1;
- y = p2;
- }
+ public int X { get; init; } = x;
+ public int Y { get; init; } = y;
}
//
@@ -127,7 +122,7 @@ static void Declarations()
static void DeclarationAndAssignment()
{
//
- MyClass myClass = new MyClass();
+ MyClass myClass = new();
MyClass myClass2 = myClass;
//
}
@@ -135,7 +130,7 @@ static void DeclarationAndAssignment()
static void InterfaceAssignment()
{
//
- MyClass myClass = new MyClass();
+ MyClass myClass = new();
// Declare and assign using an existing value.
IMyInterface myInterface = myClass;
diff --git a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsProgGuideTypes/CS/Class1.cs b/samples/snippets/csharp/VS_Snippets_VBCSharp/CsProgGuideTypes/CS/Class1.cs
index 9196f9a47fa56..100f02501b775 100644
--- a/samples/snippets/csharp/VS_Snippets_VBCSharp/CsProgGuideTypes/CS/Class1.cs
+++ b/samples/snippets/csharp/VS_Snippets_VBCSharp/CsProgGuideTypes/CS/Class1.cs
@@ -32,7 +32,7 @@ static void Main()
// List example.
// Create a list of objects to hold a heterogeneous collection
// of elements.
- List mixedList = new List();
+ List mixedList = [];
// Add a string element to the list.
mixedList.Add("First Group:");
@@ -79,8 +79,7 @@ static void Main()
sum += (int)mixedList[j] * (int)mixedList[j];
}
- // The sum displayed is 30, the sum of 1 + 4 + 9 + 16.
- Console.WriteLine("Sum: " + sum);
+ Console.WriteLine($"Sum: {sum}");
// Output:
// Answer42True
@@ -186,11 +185,11 @@ static void Main()
{
int j = (short)o; // attempt to unbox
- System.Console.WriteLine("Unboxing OK.");
+ Console.WriteLine("Unboxing OK.");
}
- catch (System.InvalidCastException e)
+ catch (InvalidCastException e)
{
- System.Console.WriteLine($"{e.Message} Error: Incorrect unboxing.");
+ Console.WriteLine($"{e.Message} Error: Incorrect unboxing.");
}
}
}
@@ -223,7 +222,7 @@ static void Main(string[] args)
{
//
byte[] bytes = BitConverter.GetBytes(201805978);
- Console.WriteLine("byte array: " + BitConverter.ToString(bytes));
+ Console.WriteLine($"byte array: {BitConverter.ToString(bytes)}");
// Output: byte array: 9A-50-07-0C
//
}
@@ -268,7 +267,7 @@ Hexadecimal value of ! is 21
// Convert the number expressed in base-16 to an integer.
int value = Convert.ToInt32(hex, 16);
// Get the character corresponding to the integral value.
- string stringValue = Char.ConvertFromUtf32(value);
+ string stringValue = char.ConvertFromUtf32(value);
char charValue = (char)value;
Console.WriteLine("hexadecimal value = {0}, int value = {1}, char value = {2} or {3}",
hex, value, stringValue, charValue);
@@ -291,7 +290,7 @@ Hexadecimal value of ! is 21
//
string hexString = "8E2";
- int num = Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
+ int num = int.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
Console.WriteLine(num);
//Output: 2274
//
diff --git a/samples/snippets/csharp/objectoriented/accessmodifiers.cs b/samples/snippets/csharp/objectoriented/accessmodifiers.cs
index 09f65959165d6..76d8cd76478cc 100644
--- a/samples/snippets/csharp/objectoriented/accessmodifiers.cs
+++ b/samples/snippets/csharp/objectoriented/accessmodifiers.cs
@@ -18,10 +18,7 @@ protected void Pedal() { }
private int _wheels = 3;
// protected internal property:
- protected internal int Wheels
- {
- get { return _wheels; }
- }
+ protected internal int Wheels => _wheels;
}
//
-}
+}
\ No newline at end of file