diff --git a/docs/architecture/cloud-native/relational-vs-nosql-data.md b/docs/architecture/cloud-native/relational-vs-nosql-data.md
index 3b12625a1f9b6..fa43c132c240e 100644
--- a/docs/architecture/cloud-native/relational-vs-nosql-data.md
+++ b/docs/architecture/cloud-native/relational-vs-nosql-data.md
@@ -30,7 +30,7 @@ NoSQL databases include several different models for accessing and managing data
| Wide-Column Store | Related data is stored as a set of nested-key/value pairs within a single column. |
| Graph Store | Data is stored in a graph structure as node, edge, and data properties. |
-## The CAP theorem
+## CAP and PACELC theorems
As a way to understand the differences between these types of databases, consider the CAP theorem, a set of principles applied to distributed systems that store state. Figure 5-10 shows the three properties of the CAP theorem.
@@ -46,11 +46,13 @@ The theorem states that distributed data systems will offer a trade-off between
- *Partition Tolerance.* Guarantees the system continues to operate even if a replicated data node fails or loses connectivity with other replicated data nodes.
-CAP theorem explains the tradeoffs associated with managing consistency and availability during a network partition; however tradeoffs with respect to consistency and performance also exist with the absence of a network partition. CAP theorem is often further extended to [PACELC](http://www.cs.umd.edu/~abadi/papers/abadi-pacelc.pdf) to explain the tradeoffs more comprehensively.
+CAP theorem explains the tradeoffs associated with managing consistency and availability during a network partition; however tradeoffs with respect to consistency and performance also exist with the absence of a network partition.
> [!NOTE]
> Even if you choose availability over consistency, in times of network partition, availability will suffer. CAP available system is more available to some of its clients but it's not necessarily "highly available" to all its clients.
+CAP theorem is often further extended to [PACELC](http://www.cs.umd.edu/~abadi/papers/abadi-pacelc.pdf) to explain the tradeoffs more comprehensively. The CAP theorem is particularly relevant in intermittently connected environments, such as those related to the Internet of Things (IoT), environmental monitoring, and mobile applications. In these contexts, devices may become partitioned due to challenging physical conditions, such as power outages or when entering confined spaces like elevators. For distributed systems, such as cloud applications, it is more appropriate to use the PACELC theorem, which is more comprehensive and considers trade-offs such as latency and consistency even in the absence of network partitions.
+
Relational databases typically provide consistency and availability, but not partition tolerance. They're typically provisioned to a single server and scale vertically by adding more resources to the machine.
Many relational database systems support built-in replication features where copies of the primary database can be made to other secondary server instances. Write operations are made to the primary instance and replicated to each of the secondaries. Upon a failure, the primary instance can fail over to a secondary to provide high availability. Secondaries can also be used to distribute read operations. While writes operations always go against the primary replica, read operations can be routed to any of the secondaries to reduce system load.
diff --git a/docs/architecture/modern-web-apps-azure/index.md b/docs/architecture/modern-web-apps-azure/index.md
index 714f3c43ffb28..0cc3332740d83 100644
--- a/docs/architecture/modern-web-apps-azure/index.md
+++ b/docs/architecture/modern-web-apps-azure/index.md
@@ -8,6 +8,12 @@ ms.date: 01/10/2022
# Architect Modern Web Applications with ASP.NET Core and Azure
+Before reading this article, we recommend you first read [Modern Web App pattern for .NET](/azure/architecture/web-apps/guides/enterprise-app-patterns/modern-web-app/dotnet/guidance). The [Modern Web App pattern for .NET](/azure/architecture/web-apps/guides/enterprise-app-patterns/modern-web-app/dotnet/guidance) article:
+
+* Is Microsoft's recommended guide to modern web app patterns. It provides a prescriptive architecture, code, and configuration guidance on how to modernize web apps in the cloud.
+* Provides a [GitHub reference implementation](https://github.com/Azure/modern-web-app-pattern-dotnet): A production-grade web app that uses best practices. Contains concrete examples to build Modern Web Apps in Azure.
+* Is more up to date than this article and is actively updated.
+

**EDITION v8.0** - Updated to ASP.NET Core 8.0
diff --git a/docs/azure/TOC.yml b/docs/azure/TOC.yml
index c0f02e227efdd..402d6fad001a1 100644
--- a/docs/azure/TOC.yml
+++ b/docs/azure/TOC.yml
@@ -75,6 +75,8 @@
href: ./sdk/authentication/additional-methods.md
- name: Credential chains
href: ./sdk/authentication/credential-chains.md
+ - name: Best practices
+ href: ./sdk/authentication/authentication-best-practices.md
- name: ASP.NET Core guidance
href: ./sdk/aspnetcore-guidance.md
- name: Resource management
diff --git a/docs/azure/includes/dotnet-all.md b/docs/azure/includes/dotnet-all.md
index 472cd4d048e97..88e5c49f78a9a 100644
--- a/docs/azure/includes/dotnet-all.md
+++ b/docs/azure/includes/dotnet-all.md
@@ -68,7 +68,7 @@
| Maps Search | NuGet [2.0.0-beta.4](https://www.nuget.org/packages/Azure.Maps.Search/2.0.0-beta.4) | [docs](/dotnet/api/overview/azure/Maps.Search-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [2.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Maps.Search_2.0.0-beta.4/sdk/maps/Azure.Maps.Search/) |
| Media Analytics Edge | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.Media.Analytics.Edge/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/Media.Analytics.Edge-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Media.Analytics.Edge_1.0.0-beta.1/sdk/mediaservices/Azure.Media.Analytics.Edge) |
| Metrics Advisor | NuGet [1.1.0](https://www.nuget.org/packages/Azure.AI.MetricsAdvisor/1.1.0) | [docs](/dotnet/api/overview/azure/AI.MetricsAdvisor-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.MetricsAdvisor_1.1.0/sdk/metricsadvisor/Azure.AI.MetricsAdvisor/) |
-| Microsoft Playwright Testing | NuGet [1.0.0-beta.3](https://www.nuget.org/packages/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/1.0.0-beta.3) | [docs](/dotnet/api/overview/azure/Developer.MicrosoftPlaywrightTesting.TestLogger-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger_1.0.0-beta.3/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/) |
+| Microsoft Playwright Testing | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/Developer.MicrosoftPlaywrightTesting.TestLogger-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger_1.0.0-beta.4/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/) |
| Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents | NuGet [1.0.1](https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/1.0.1) | [docs](/dotnet/api/overview/azure/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents_1.0.1/sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/) |
| Microsoft.Azure.WebPubSub.AspNetCore | NuGet [1.4.0](https://www.nuget.org/packages/Microsoft.Azure.WebPubSub.AspNetCore/1.4.0) | [docs](/dotnet/api/overview/azure/Microsoft.Azure.WebPubSub.AspNetCore-readme) | GitHub [1.4.0](https://github.com/Azure/azure-sdk-for-net/tree/Microsoft.Azure.WebPubSub.AspNetCore_1.4.0/sdk/webpubsub/Microsoft.Azure.WebPubSub.AspNetCore/) |
| Microsoft.Azure.WebPubSub.Common | NuGet [1.4.0](https://www.nuget.org/packages/Microsoft.Azure.WebPubSub.Common/1.4.0) | [docs](/dotnet/api/overview/azure/Microsoft.Azure.WebPubSub.Common-readme) | GitHub [1.4.0](https://github.com/Azure/azure-sdk-for-net/tree/Microsoft.Azure.WebPubSub.Common_1.4.0/sdk/webpubsub/Microsoft.Azure.WebPubSub.Common/) |
@@ -76,7 +76,7 @@
| Models Repository | NuGet [1.0.0-preview.6](https://www.nuget.org/packages/Azure.IoT.ModelsRepository/1.0.0-preview.6) | [docs](/dotnet/api/overview/azure/IoT.ModelsRepository-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-preview.6](https://github.com/Azure/azure-sdk-for-net/tree/Azure.IoT.ModelsRepository_1.0.0-preview.6/sdk/modelsrepository/Azure.IoT.ModelsRepository/) |
| Monitor Ingestion | NuGet [1.1.2](https://www.nuget.org/packages/Azure.Monitor.Ingestion/1.1.2) | [docs](/dotnet/api/overview/azure/Monitor.Ingestion-readme) | GitHub [1.1.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Monitor.Ingestion_1.1.2/sdk/monitor/Azure.Monitor.Ingestion/) |
| Monitor Query | NuGet [1.6.0](https://www.nuget.org/packages/Azure.Monitor.Query/1.6.0) | [docs](/dotnet/api/overview/azure/Monitor.Query-readme) | GitHub [1.6.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Monitor.Query_1.6.0/sdk/monitor/Azure.Monitor.Query/) |
-| NUnit ? Microsoft Playwright Testing | NuGet [1.0.0-beta.3](https://www.nuget.org/packages/Azure.Developer.MicrosoftPlaywrightTesting.NUnit/1.0.0-beta.3) | [docs](/dotnet/api/overview/azure/Developer.MicrosoftPlaywrightTesting.NUnit-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Developer.MicrosoftPlaywrightTesting.NUnit_1.0.0-beta.3/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.NUnit/) |
+| NUnit ? Microsoft Playwright Testing | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.Developer.MicrosoftPlaywrightTesting.NUnit/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/Developer.MicrosoftPlaywrightTesting.NUnit-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Developer.MicrosoftPlaywrightTesting.NUnit_1.0.0-beta.4/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.NUnit/) |
| OpenAI Assistants | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.AI.OpenAI.Assistants/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/AI.OpenAI.Assistants-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.OpenAI.Assistants_1.0.0-beta.4/sdk/openai/Azure.AI.OpenAI.Assistants/) |
| OpenAI Inference | NuGet [2.1.0](https://www.nuget.org/packages/Azure.AI.OpenAI/2.1.0) | [docs](/dotnet/api/overview/azure/AI.OpenAI-readme) | GitHub [2.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.OpenAI_2.1.0/sdk/openai/Azure.AI.OpenAI/) |
| OpenTelemetry AspNetCore | NuGet [1.2.0](https://www.nuget.org/packages/Azure.Monitor.OpenTelemetry.AspNetCore/1.2.0) NuGet [1.3.0-beta.2](https://www.nuget.org/packages/Azure.Monitor.OpenTelemetry.AspNetCore/1.3.0-beta.2) | [docs](/dotnet/api/overview/azure/Monitor.OpenTelemetry.AspNetCore-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Monitor.OpenTelemetry.AspNetCore_1.2.0/sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/) GitHub [1.3.0-beta.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Monitor.OpenTelemetry.AspNetCore_1.3.0-beta.2/sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/) |
@@ -95,7 +95,7 @@
| Question Answering | NuGet [1.1.0](https://www.nuget.org/packages/Azure.AI.Language.QuestionAnswering/1.1.0) | [docs](/dotnet/api/overview/azure/AI.Language.QuestionAnswering-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.Language.QuestionAnswering_1.1.0/sdk/cognitivelanguage/Azure.AI.Language.QuestionAnswering/) |
| Schema Registry | NuGet [1.4.0](https://www.nuget.org/packages/Azure.Data.SchemaRegistry/1.4.0) | [docs](/dotnet/api/overview/azure/Data.SchemaRegistry-readme) | GitHub [1.4.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Data.SchemaRegistry_1.4.0/sdk/schemaregistry/Azure.Data.SchemaRegistry/) |
| Schema Registry - Avro | NuGet [1.0.1](https://www.nuget.org/packages/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/1.0.1) | [docs](/dotnet/api/overview/azure/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro_1.0.1/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/) |
-| Service Bus | NuGet [7.18.2](https://www.nuget.org/packages/Azure.Messaging.ServiceBus/7.18.2) | [docs](/dotnet/api/overview/azure/Messaging.ServiceBus-readme) | GitHub [7.18.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Messaging.ServiceBus_7.18.2/sdk/servicebus/Azure.Messaging.ServiceBus/) |
+| Service Bus | NuGet [7.18.3](https://www.nuget.org/packages/Azure.Messaging.ServiceBus/7.18.3) | [docs](/dotnet/api/overview/azure/Messaging.ServiceBus-readme) | GitHub [7.18.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Messaging.ServiceBus_7.18.3/sdk/servicebus/Azure.Messaging.ServiceBus/) |
| Storage - Blobs | NuGet [12.23.0](https://www.nuget.org/packages/Azure.Storage.Blobs/12.23.0) | [docs](/dotnet/api/overview/azure/Storage.Blobs-readme) | GitHub [12.23.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Storage.Blobs_12.23.0/sdk/storage/Azure.Storage.Blobs/) |
| Storage - Blobs Batch | NuGet [12.20.0](https://www.nuget.org/packages/Azure.Storage.Blobs.Batch/12.20.0) | [docs](/dotnet/api/overview/azure/Storage.Blobs.Batch-readme) | GitHub [12.20.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Storage.Blobs.Batch_12.20.0/sdk/storage/Azure.Storage.Blobs.Batch/) |
| Storage - Blobs ChangeFeed | NuGet [12.0.0-preview.52](https://www.nuget.org/packages/Azure.Storage.Blobs.ChangeFeed/12.0.0-preview.52) | [docs](/dotnet/api/overview/azure/Storage.Blobs.ChangeFeed-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [12.0.0-preview.52](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Storage.Blobs.ChangeFeed_12.0.0-preview.52/sdk/storage/Azure.Storage.Blobs.ChangeFeed/) |
diff --git a/docs/azure/includes/dotnet-new.md b/docs/azure/includes/dotnet-new.md
index 9a92cbe25b2ad..32d250495b467 100644
--- a/docs/azure/includes/dotnet-new.md
+++ b/docs/azure/includes/dotnet-new.md
@@ -69,7 +69,7 @@
| Maps Search | NuGet [2.0.0-beta.4](https://www.nuget.org/packages/Azure.Maps.Search/2.0.0-beta.4) | [docs](/dotnet/api/overview/azure/Maps.Search-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [2.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Maps.Search_2.0.0-beta.4/sdk/maps/Azure.Maps.Search/) |
| Media Analytics Edge | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.Media.Analytics.Edge/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/Media.Analytics.Edge-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Media.Analytics.Edge_1.0.0-beta.1/sdk/mediaservices/Azure.Media.Analytics.Edge) |
| Metrics Advisor | NuGet [1.1.0](https://www.nuget.org/packages/Azure.AI.MetricsAdvisor/1.1.0) | [docs](/dotnet/api/overview/azure/AI.MetricsAdvisor-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.MetricsAdvisor_1.1.0/sdk/metricsadvisor/Azure.AI.MetricsAdvisor/) |
-| Microsoft Playwright Testing | NuGet [1.0.0-beta.3](https://www.nuget.org/packages/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/1.0.0-beta.3) | [docs](/dotnet/api/overview/azure/Developer.MicrosoftPlaywrightTesting.TestLogger-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger_1.0.0-beta.3/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/) |
+| Microsoft Playwright Testing | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/Developer.MicrosoftPlaywrightTesting.TestLogger-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger_1.0.0-beta.4/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/) |
| Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents | NuGet [1.0.1](https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/1.0.1) | [docs](/dotnet/api/overview/azure/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents_1.0.1/sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/) |
| Microsoft.Azure.WebPubSub.AspNetCore | NuGet [1.4.0](https://www.nuget.org/packages/Microsoft.Azure.WebPubSub.AspNetCore/1.4.0) | [docs](/dotnet/api/overview/azure/Microsoft.Azure.WebPubSub.AspNetCore-readme) | GitHub [1.4.0](https://github.com/Azure/azure-sdk-for-net/tree/Microsoft.Azure.WebPubSub.AspNetCore_1.4.0/sdk/webpubsub/Microsoft.Azure.WebPubSub.AspNetCore/) |
| Microsoft.Azure.WebPubSub.Common | NuGet [1.4.0](https://www.nuget.org/packages/Microsoft.Azure.WebPubSub.Common/1.4.0) | [docs](/dotnet/api/overview/azure/Microsoft.Azure.WebPubSub.Common-readme) | GitHub [1.4.0](https://github.com/Azure/azure-sdk-for-net/tree/Microsoft.Azure.WebPubSub.Common_1.4.0/sdk/webpubsub/Microsoft.Azure.WebPubSub.Common/) |
@@ -77,7 +77,7 @@
| Models Repository | NuGet [1.0.0-preview.6](https://www.nuget.org/packages/Azure.IoT.ModelsRepository/1.0.0-preview.6) | [docs](/dotnet/api/overview/azure/IoT.ModelsRepository-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-preview.6](https://github.com/Azure/azure-sdk-for-net/tree/Azure.IoT.ModelsRepository_1.0.0-preview.6/sdk/modelsrepository/Azure.IoT.ModelsRepository/) |
| Monitor Ingestion | NuGet [1.1.2](https://www.nuget.org/packages/Azure.Monitor.Ingestion/1.1.2) | [docs](/dotnet/api/overview/azure/Monitor.Ingestion-readme) | GitHub [1.1.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Monitor.Ingestion_1.1.2/sdk/monitor/Azure.Monitor.Ingestion/) |
| Monitor Query | NuGet [1.6.0](https://www.nuget.org/packages/Azure.Monitor.Query/1.6.0) | [docs](/dotnet/api/overview/azure/Monitor.Query-readme) | GitHub [1.6.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Monitor.Query_1.6.0/sdk/monitor/Azure.Monitor.Query/) |
-| NUnit ? Microsoft Playwright Testing | NuGet [1.0.0-beta.3](https://www.nuget.org/packages/Azure.Developer.MicrosoftPlaywrightTesting.NUnit/1.0.0-beta.3) | [docs](/dotnet/api/overview/azure/Developer.MicrosoftPlaywrightTesting.NUnit-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Developer.MicrosoftPlaywrightTesting.NUnit_1.0.0-beta.3/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.NUnit/) |
+| NUnit ? Microsoft Playwright Testing | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.Developer.MicrosoftPlaywrightTesting.NUnit/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/Developer.MicrosoftPlaywrightTesting.NUnit-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Developer.MicrosoftPlaywrightTesting.NUnit_1.0.0-beta.4/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.NUnit/) |
| OpenAI Assistants | NuGet [1.0.0-beta.4](https://www.nuget.org/packages/Azure.AI.OpenAI.Assistants/1.0.0-beta.4) | [docs](/dotnet/api/overview/azure/AI.OpenAI.Assistants-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.4](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.OpenAI.Assistants_1.0.0-beta.4/sdk/openai/Azure.AI.OpenAI.Assistants/) |
| OpenAI Inference | NuGet [2.1.0](https://www.nuget.org/packages/Azure.AI.OpenAI/2.1.0) | [docs](/dotnet/api/overview/azure/AI.OpenAI-readme) | GitHub [2.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.OpenAI_2.1.0/sdk/openai/Azure.AI.OpenAI/) |
| OpenTelemetry AspNetCore | NuGet [1.2.0](https://www.nuget.org/packages/Azure.Monitor.OpenTelemetry.AspNetCore/1.2.0) NuGet [1.3.0-beta.2](https://www.nuget.org/packages/Azure.Monitor.OpenTelemetry.AspNetCore/1.3.0-beta.2) | [docs](/dotnet/api/overview/azure/Monitor.OpenTelemetry.AspNetCore-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Monitor.OpenTelemetry.AspNetCore_1.2.0/sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/) GitHub [1.3.0-beta.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Monitor.OpenTelemetry.AspNetCore_1.3.0-beta.2/sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/) |
@@ -99,7 +99,7 @@
| Question Answering | NuGet [1.1.0](https://www.nuget.org/packages/Azure.AI.Language.QuestionAnswering/1.1.0) | [docs](/dotnet/api/overview/azure/AI.Language.QuestionAnswering-readme) | GitHub [1.1.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.Language.QuestionAnswering_1.1.0/sdk/cognitivelanguage/Azure.AI.Language.QuestionAnswering/) |
| Schema Registry | NuGet [1.4.0](https://www.nuget.org/packages/Azure.Data.SchemaRegistry/1.4.0) | [docs](/dotnet/api/overview/azure/Data.SchemaRegistry-readme) | GitHub [1.4.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Data.SchemaRegistry_1.4.0/sdk/schemaregistry/Azure.Data.SchemaRegistry/) |
| Schema Registry - Avro | NuGet [1.0.1](https://www.nuget.org/packages/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/1.0.1) | [docs](/dotnet/api/overview/azure/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro-readme) | GitHub [1.0.1](https://github.com/Azure/azure-sdk-for-net/tree/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro_1.0.1/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/) |
-| Service Bus | NuGet [7.18.2](https://www.nuget.org/packages/Azure.Messaging.ServiceBus/7.18.2) | [docs](/dotnet/api/overview/azure/Messaging.ServiceBus-readme) | GitHub [7.18.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Messaging.ServiceBus_7.18.2/sdk/servicebus/Azure.Messaging.ServiceBus/) |
+| Service Bus | NuGet [7.18.3](https://www.nuget.org/packages/Azure.Messaging.ServiceBus/7.18.3) | [docs](/dotnet/api/overview/azure/Messaging.ServiceBus-readme) | GitHub [7.18.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Messaging.ServiceBus_7.18.3/sdk/servicebus/Azure.Messaging.ServiceBus/) |
| Storage - Blobs | NuGet [12.23.0](https://www.nuget.org/packages/Azure.Storage.Blobs/12.23.0) | [docs](/dotnet/api/overview/azure/Storage.Blobs-readme) | GitHub [12.23.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Storage.Blobs_12.23.0/sdk/storage/Azure.Storage.Blobs/) |
| Storage - Blobs Batch | NuGet [12.20.0](https://www.nuget.org/packages/Azure.Storage.Blobs.Batch/12.20.0) | [docs](/dotnet/api/overview/azure/Storage.Blobs.Batch-readme) | GitHub [12.20.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Storage.Blobs.Batch_12.20.0/sdk/storage/Azure.Storage.Blobs.Batch/) |
| Storage - Blobs ChangeFeed | NuGet [12.0.0-preview.52](https://www.nuget.org/packages/Azure.Storage.Blobs.ChangeFeed/12.0.0-preview.52) | [docs](/dotnet/api/overview/azure/Storage.Blobs.ChangeFeed-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [12.0.0-preview.52](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Storage.Blobs.ChangeFeed_12.0.0-preview.52/sdk/storage/Azure.Storage.Blobs.ChangeFeed/) |
diff --git a/docs/azure/sdk/authentication/authentication-best-practices.md b/docs/azure/sdk/authentication/authentication-best-practices.md
new file mode 100644
index 0000000000000..901ae92d5c5bc
--- /dev/null
+++ b/docs/azure/sdk/authentication/authentication-best-practices.md
@@ -0,0 +1,74 @@
+---
+title: Authentication best practices with the Azure Identity library for .NET
+description: This article describes authentication best practices to follow when using the Azure Identity library for .NET.
+ms.topic: conceptual
+ms.date: 01/15/2025
+---
+
+# Authentication best practices with the Azure Identity library for .NET
+
+This article offers guidelines to help you maximize the performance and reliability of your .NET apps when authenticating to Azure services. To make the most of the Azure Identity library for .NET, it's important to understand potential issues and mitigation techniques.
+
+## Use deterministic credentials in production environments
+
+[`DefaultAzureCredential`](/dotnet/azure/sdk/authentication/credential-chains?tabs=dac#defaultazurecredential-overview) is the most approachable way to get started with the Azure Identity library, but that convenience also introduces certain tradeoffs. Most notably, the specific credential in the chain that will succeed and be used for request authentication can't be guaranteed ahead of time. In a production environment, this unpredictability can introduce significant and sometimes subtle problems.
+
+For example, consider the following hypothetical sequence of events:
+
+1. An organization's security team mandates all apps use managed identity to authenticate to Azure resources.
+1. For months, a .NET app hosted on an Azure Virtual Machine (VM) successfully uses `DefaultAzureCredential` to authenticate via managed identity.
+1. Without telling the support team, a developer installs the Azure CLI on that VM and runs the `az login` command to authenticate to Azure.
+1. Due to a separate configuration change in the Azure environment, authentication via the original managed identity unexpectedly begins to fail silently.
+1. `DefaultAzureCredential` skips the failed `ManagedIdentityCredential` and searches for the next available credential, which is `AzureCliCredential`.
+1. The application starts utilizing the Azure CLI credentials rather than the managed identity, which may fail or result in unexpected elevation or reduction of privileges.
+
+To prevent these types of subtle issues or silent failures in production apps, strongly consider moving from `DefaultAzureCredential` to one of the following deterministic solutions:
+
+- A specific `TokenCredential` implementation, such as `ManagedIdentityCredential`. See the [**Derived** list](/dotnet/api/azure.core.tokencredential?view=azure-dotnet&preserve-view=true#definition) for options.
+- A pared-down `ChainedTokenCredential` implementation optimized for the Azure environment in which your app runs. `ChainedTokenCredential` essentially creates a specific allow-list of acceptable credential options, such as `ManagedIdentity` for production and `VisualStudioCredential` for development.
+
+For example, consider the following `DefaultAzureCredential` configuration in an ASP.NET Core project:
+
+:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_Dac" highlight="6,7":::
+
+Replace the preceding code with a `ChainedTokenCredential` implementation that specifies only the necessary credentials:
+
+:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_Ctc" highlight="6-8":::
+
+In this example, `ManagedIdentityCredential` would be automatically discovered in production, while `VisualStudioCredential` would work in local development environments.
+
+## Reuse credential instances
+
+Reuse credential instances when possible to improve app resilience and reduce the number of access token requests issued to Microsoft Entra ID. When a credential is reused, an attempt is made to fetch a token from the app token cache managed by the underlying MSAL dependency. For more information, see [Token caching in the Azure Identity client library](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/samples/TokenCache.md).
+
+> [!IMPORTANT]
+> A high-volume app that doesn't reuse credentials may encounter HTTP 429 throttling responses from Microsoft Entra ID, which can lead to app outages.
+
+The recommended credential reuse strategy differs by .NET application type.
+
+# [ASP.NET Core](#tab/aspdotnet)
+
+Implement credential reuse through the `UseCredential` method of `Microsoft.Extensions.Azure`:
+
+:::code language="csharp" source="../snippets/authentication/best-practices/Program.cs" id="snippet_credential_reuse_Dac" highlight="6" :::
+
+For information on this approach, see [Authenticate using Microsoft Entra ID](/dotnet/azure/sdk/aspnetcore-guidance?tabs=api#authenticate-using-microsoft-entra-id).
+
+# [Other](#tab/other)
+
+:::code language="csharp" source="../snippets/authentication/best-practices/Program.cs" id="snippet_credential_reuse_noDac" highlight="8, 12" :::
+
+---
+
+## Understand the managed identity retry strategy
+
+The Azure Identity library for .NET allows you to authenticate via managed identity with `ManagedIdentityCredential`. The way in which you use `ManagedIdentityCredential` impacts the applied retry strategy. When used via:
+
+- `DefaultAzureCredential`, no retries are attempted when the initial token acquisition attempt fails or times out after a short duration. This is the least resilient option because it is optimized to "fail fast" for an efficient development inner-loop.
+- Any other approach, such as `ChainedTokenCredential` or `ManagedIdentityCredential` directly:
+ - The time interval between retries starts at 0.8 seconds, and a maximum of five retries are attempted, by default. This option is optimized for resilience but introduces potentially unwanted delays in the development inner-loop.
+ - To change any of the default retry settings, use the `Retry` property on `ManagedIdentityCredentialOptions`. For example, retry a maximum of three times, with a starting interval of 0.5 seconds:
+
+ :::code language="csharp" source="../snippets/authentication/best-practices/Program.cs" id="snippet_retries" highlight="5-9" :::
+
+For more information on customizing retry policies, see [Setting a custom retry policy](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/samples/Configuration.md#setting-a-custom-retry-policy).
diff --git a/docs/azure/sdk/snippets/authentication/Directory.Packages.props b/docs/azure/sdk/snippets/authentication/Directory.Packages.props
index 49ef5dc43aac3..6a7584c99a6ae 100644
--- a/docs/azure/sdk/snippets/authentication/Directory.Packages.props
+++ b/docs/azure/sdk/snippets/authentication/Directory.Packages.props
@@ -4,10 +4,11 @@
+
+
-
diff --git a/docs/azure/sdk/snippets/authentication/best-practices/AuthBestPractices.csproj b/docs/azure/sdk/snippets/authentication/best-practices/AuthBestPractices.csproj
new file mode 100644
index 0000000000000..5e7b705f2e39c
--- /dev/null
+++ b/docs/azure/sdk/snippets/authentication/best-practices/AuthBestPractices.csproj
@@ -0,0 +1,16 @@
+
+
+
+ net9.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/azure/sdk/snippets/authentication/best-practices/Program.cs b/docs/azure/sdk/snippets/authentication/best-practices/Program.cs
new file mode 100644
index 0000000000000..434b8c3825345
--- /dev/null
+++ b/docs/azure/sdk/snippets/authentication/best-practices/Program.cs
@@ -0,0 +1,81 @@
+using Azure.Identity;
+using Azure.Security.KeyVault.Secrets;
+using Azure.Storage.Blobs;
+using Microsoft.Extensions.Azure;
+
+var userAssignedClientId = "";
+var builder = WebApplication.CreateBuilder(args);
+
+#region snippet_credential_reuse_Dac
+builder.Services.AddAzureClients(clientBuilder =>
+{
+ clientBuilder.AddSecretClient(new Uri(""));
+ clientBuilder.AddBlobServiceClient(new Uri(""));
+
+ clientBuilder.UseCredential(new DefaultAzureCredential());
+});
+#endregion snippet_credential_reuse_Dac
+
+#region snippet_credential_reuse_noDac
+ChainedTokenCredential credentialChain = new(
+ new ManagedIdentityCredential(
+ ManagedIdentityId.FromUserAssignedClientId(userAssignedClientId)),
+ new VisualStudioCredential());
+
+BlobServiceClient blobServiceClient = new(
+ new Uri(""),
+ credentialChain);
+
+SecretClient secretClient = new(
+ new Uri(""),
+ credentialChain);
+#endregion snippet_credential_reuse_noDac
+
+#region snippet_retries
+ManagedIdentityCredentialOptions miCredentialOptions = new(
+ ManagedIdentityId.FromUserAssignedClientId(userAssignedClientId)
+ )
+ {
+ Retry =
+ {
+ MaxRetries = 3,
+ Delay = TimeSpan.FromSeconds(0.5),
+ }
+ };
+ ChainedTokenCredential tokenChain = new(
+ new ManagedIdentityCredential(miCredentialOptions),
+ new VisualStudioCredential()
+ );
+#endregion
+
+builder.Services.AddEndpointsApiExplorer();
+
+var app = builder.Build();
+
+app.UseHttpsRedirection();
+
+var summaries = new[]
+{
+ "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
+};
+
+app.MapGet("/weatherforecast", () =>
+{
+ var forecast = Enumerable.Range(1, 5).Select(index =>
+ new WeatherForecast
+ (
+ DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
+ Random.Shared.Next(-20, 55),
+ summaries[Random.Shared.Next(summaries.Length)]
+ ))
+ .ToArray();
+ return forecast;
+})
+.WithName("GetWeatherForecast");
+
+app.Run();
+
+internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
+{
+ public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+}
diff --git a/docs/azure/sdk/snippets/authentication/best-practices/Properties/launchSettings.json b/docs/azure/sdk/snippets/authentication/best-practices/Properties/launchSettings.json
new file mode 100644
index 0000000000000..12166b5665976
--- /dev/null
+++ b/docs/azure/sdk/snippets/authentication/best-practices/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "profiles": {
+ "AuthBestPractices": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:56902;http://localhost:56903"
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/azure/sdk/snippets/authentication/best-practices/appsettings.Development.json b/docs/azure/sdk/snippets/authentication/best-practices/appsettings.Development.json
new file mode 100644
index 0000000000000..0c208ae9181e5
--- /dev/null
+++ b/docs/azure/sdk/snippets/authentication/best-practices/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/docs/azure/sdk/snippets/authentication/best-practices/appsettings.json b/docs/azure/sdk/snippets/authentication/best-practices/appsettings.json
new file mode 100644
index 0000000000000..10f68b8c8b4f7
--- /dev/null
+++ b/docs/azure/sdk/snippets/authentication/best-practices/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/docs/core/additional-tools/dotnet-coverage.md b/docs/core/additional-tools/dotnet-coverage.md
index c7c478f5b8e73..2c1c765f4ba0d 100644
--- a/docs/core/additional-tools/dotnet-coverage.md
+++ b/docs/core/additional-tools/dotnet-coverage.md
@@ -11,7 +11,7 @@ ms.topic: reference
## Synopsis
```console
-dotnet-coverage [-h, --help] [--version]
+dotnet-coverage [-h, --help] [--version]
```
## Description
@@ -49,6 +49,7 @@ dotnet tool install --global dotnet-coverage
| [dotnet-coverage snapshot](#dotnet-coverage-snapshot) |
| [dotnet-coverage shutdown](#dotnet-coverage-shutdown) |
| [dotnet-coverage instrument](#dotnet-coverage-instrument) |
+| [dotnet-coverage uninstrument](#dotnet-coverage-uninstrument) |
## dotnet-coverage merge
@@ -62,10 +63,12 @@ The `merge` command is used to merge several code coverage reports into one. Thi
```console
dotnet-coverage merge
+ ...
[--remove-input-files]
[-o|--output ] [-f|--output-format ]
- [-l|--log-file ] [-ll|--log-level ] [-?|-h|--help]
-
+ [-l|--log-file ] [-ll|--log-level ]
+ [-dco|--disable-console-output] [--nologo]
+ [-?|-h|--help]
```
### Arguments
@@ -100,6 +103,14 @@ dotnet-coverage merge
Sets the log level. Supported values: `Error`, `Info`, and `Verbose`.
+* **`-dco|--disable-console-output`**
+
+ Disables console output.
+
+* **`--nologo`**
+
+ Do not display Code Coverage banner.
+
## dotnet-coverage collect
The `collect` command is used to collect code coverage data for any .NET process and its subprocesses. For example, you can collect code coverage data for a console application or a Blazor application. This command supports dynamic and static instrumentation. Static instrumentation is available on all platforms. You can specify files to be statically instrumented using `include-files` option. Dynamic instrumentation is available on Windows (x86, x64 and Arm64), Linux (x64), and macOS (x64). The command supports only .NET modules. Native modules are not supported.
@@ -114,11 +125,12 @@ The `collect` command will collect code coverage for the given process executed
```console
dotnet-coverage collect
+ ...
[-s|--settings ] [-id|--session-id ]
- [-if|--include-files ] [-o|--output ]
- [-f|--output-format ] [-l|--log-file ]
- [-ll|--log-level ] [-?|-h|--help]
-
+ [-if|--include-files ] [-o|--output ] [-f|--output-format ]
+ [-l|--log-file ] [-ll|--log-level ]
+ [-dco|--disable-console-output] [--nologo]
+ [-?|-h|--help]
```
#### Server Mode
@@ -129,9 +141,10 @@ The `collect` command hosts a server for code coverage collection. Clients can c
dotnet-coverage collect
[-s|--settings ] [-id|--session-id ]
[-sv|--server-mode] [-b|--background] [-t|--timeout]
- [-if|--include-files ] [-o|--output ]
- [-f|--output-format ] [-l|--log-file ]
- [-ll|--log-level ] [-?|-h|--help]
+ [-if|--include-files ] [-o|--output ] [-f|--output-format ]
+ [-l|--log-file ] [-ll|--log-level ]
+ [-dco|--disable-console-output] [--nologo]
+ [-?|-h|--help]
```
### Arguments
@@ -186,6 +199,14 @@ dotnet-coverage collect
Sets the log level. Supported values: `Error`, `Info`, and `Verbose`.
+* **`-dco|--disable-console-output`**
+
+ Disables console output.
+
+* **`--nologo`**
+
+ Do not display Code Coverage banner.
+
## dotnet-coverage connect
The `connect` command is used to connect with the existing server and collects code coverage data for any .NET process and its subprocesses. For example, you can collect code coverage data for a console application or a Blazor application. The command supports only .NET modules. Native modules are not supported.
@@ -197,10 +218,11 @@ The `connect` command is used to connect with the existing server and collects c
```console
dotnet-coverage connect
+ ...
[-b|--background] [-t|--timeout]
- [-l|--log-file ] [-ll|--log-level ] [-?|-h|--help]
-
-
+ [-l|--log-file ] [-ll|--log-level ]
+ [-dco|--disable-console-output] [--nologo]
+ [-?|-h|--help]
```
### Arguments
@@ -235,6 +257,14 @@ dotnet-coverage connect
Sets the log level. Supported values: `Error`, `Info`, and `Verbose`.
+* **`-dco|--disable-console-output`**
+
+ Disables console output.
+
+* **`--nologo`**
+
+ Do not display Code Coverage banner.
+
## dotnet-coverage snapshot
Creates a coverage file for existing code coverage collection.
@@ -243,12 +273,14 @@ Creates a coverage file for existing code coverage collection.
```console
dotnet-coverage snapshot
+
[-r|--reset]
- [-o|--output ]
[-tn|--tag-name ] [-tid|--tag-identifier ]
+ [-o|--output ]
[-t|--timeout]
- [-l|--log-file ] [-ll|--log-level ] [-?|-h|--help]
-
+ [-l|--log-file ] [-ll|--log-level ]
+ [-dco|--disable-console-output] [--nologo]
+ [-?|-h|--help]
```
### Arguments
@@ -263,10 +295,6 @@ dotnet-coverage snapshot
Clears existing coverage information after a coverage file is created.
-* **`-o|--output `**
-
- Sets the code coverage report output file. If not provided, it's generated automatically with a timestamp.
-
* **`-tn|--tag-name `**
Creates a snapshot tag name in the coverage file with current coverage information. Tag-name and tag-identifier are mutually inclusive.
@@ -275,6 +303,10 @@ dotnet-coverage snapshot
Creates a snapshot tag identifier in the coverage file with current coverage information. Tag-name and tag-identifier are mutually inclusive.
+* **`-o|--output `**
+
+ Sets the code coverage report output file. If not provided, it's generated automatically with a timestamp.
+
* **`-t|--timeout`**
Timeout (in milliseconds) for interprocess communication between the client and the server.
@@ -287,6 +319,14 @@ dotnet-coverage snapshot
Sets the log level. Supported values: `Error`, `Info`, and `Verbose`.
+* **`-dco|--disable-console-output`**
+
+ Disables console output.
+
+* **`--nologo`**
+
+ Do not display Code Coverage banner.
+
## dotnet-coverage shutdown
Closes existing code coverage collection.
@@ -295,9 +335,11 @@ Closes existing code coverage collection.
```console
dotnet-coverage shutdown
- [-t|--timeout]
- [-l|--log-file ] [-ll|--log-level ] [-?|-h|--help]
+ [-t|--timeout]
+ [-l|--log-file ] [-ll|--log-level ]
+ [-dco|--disable-console-output] [--nologo]
+ [-?|-h|--help]
```
### Arguments
@@ -320,6 +362,14 @@ dotnet-coverage shutdown
Sets the log level. Supported values: `Error`, `Info`, and `Verbose`.
+* **`-dco|--disable-console-output`**
+
+ Disables console output.
+
+* **`--nologo`**
+
+ Do not display Code Coverage banner.
+
## dotnet-coverage instrument
The instrument command is used to instrument binary on disk.
@@ -328,10 +378,12 @@ The instrument command is used to instrument binary on disk.
```console
dotnet-coverage instrument
- [-s|--settings ] [-id|--session-id ]
- [-o|--output ] [-l|--log-file ]
- [-ll|--log-level ] [-?|-h|--help]
+ [-s|--settings ] [-id|--session-id ]
+ [-o|--output ]
+ [-l|--log-file ] [-ll|--log-level ]
+ [-dco|--disable-console-output] [--nologo]
+ [-?|-h|--help]
```
### Arguments
@@ -362,6 +414,57 @@ dotnet-coverage instrument
Sets the log level. Supported values: `Error`, `Info`, and `Verbose`.
+* **`-dco|--disable-console-output`**
+
+ Disables console output.
+
+* **`--nologo`**
+
+ Do not display Code Coverage banner.
+
+## dotnet-coverage uninstrument
+
+The uninstrument command is used to restore original binary from the instrumented binary.
+
+### Synopsis
+
+```console
+Microsoft.CodeCoverage.Console uninstrument
+
+ [-s|--settings ]
+ [-l|--log-file ] [-ll|--log-level ]
+ [-dco|--disable-console-output] [--nologo]
+ [-?|-h|--help]
+```
+
+### Arguments
+
+* **``**
+
+ The input instrumented binary.
+
+### Options
+
+* **`-s|--settings `**
+
+ Sets the path to the XML code coverage settings.
+
+* **`-l|--log-file `**
+
+ Sets the log file path. When you provide a directory (with a path separator at the end), a new log file is generated for each process under analysis.
+
+* **`-ll|--log-level `**
+
+ Sets the log level. Supported values: `Error`, `Info`, and `Verbose`.
+
+* **`-dco|--disable-console-output`**
+
+ Disables console output.
+
+* **`--nologo`**
+
+ Do not display Code Coverage banner.
+
## Sample scenarios
## Collecting code coverage
diff --git a/docs/core/testing/mstest-analyzers/mstest0001.md b/docs/core/testing/mstest-analyzers/mstest0001.md
index 72ca813aa40ec..54df7eb6b1f8d 100644
--- a/docs/core/testing/mstest-analyzers/mstest0001.md
+++ b/docs/core/testing/mstest-analyzers/mstest0001.md
@@ -44,3 +44,16 @@ To fix a violation of this rule, add `[assembly: Parallelize]` or `[assembly: Do
## When to suppress warnings
Do not suppress a warning from this rule. Many libraries can benefit from a massive performance boost when enabling parallelization. When the test application is designed in a way that prevents parallelization, having the attribute explicitly set helps new developers to understand the limitations of the library.
+
+## Suppress a warning
+
+Violations to this rule cannot be suppressed inline.
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0001.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0002.md b/docs/core/testing/mstest-analyzers/mstest0002.md
index 26ae8ddf20aac..4dfcc29f3b15a 100644
--- a/docs/core/testing/mstest-analyzers/mstest0002.md
+++ b/docs/core/testing/mstest-analyzers/mstest0002.md
@@ -46,3 +46,22 @@ Ensure that the class matches the required layout described above.
## When to suppress warnings
Do not suppress a warning from this rule. Ignoring this rule will result in tests being ignored, because MSTest will not consider this class to be a test class.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0002
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0002
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0002.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0003.md b/docs/core/testing/mstest-analyzers/mstest0003.md
index cbe6d0ee8c249..233c66ec4cfea 100644
--- a/docs/core/testing/mstest-analyzers/mstest0003.md
+++ b/docs/core/testing/mstest-analyzers/mstest0003.md
@@ -51,3 +51,22 @@ Ensure that the test method matches the required layout described above.
## When to suppress warnings
Do not suppress a warning from this rule. Ignoring this rule will result in tests being ignored, because MSTest will not consider this method to be a test method.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0003
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0003
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0003.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0004.md b/docs/core/testing/mstest-analyzers/mstest0004.md
index e7c33b6a187c1..bcffb91e7256f 100644
--- a/docs/core/testing/mstest-analyzers/mstest0004.md
+++ b/docs/core/testing/mstest-analyzers/mstest0004.md
@@ -42,3 +42,22 @@ Change the accessibility of the type to not be `public`.
## When to suppress warnings
You can suppress instances of this diagnostic if the type should remain `public` for compatibility reason.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0004
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0004
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0004.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0005.md b/docs/core/testing/mstest-analyzers/mstest0005.md
index 7b554303ab96f..bc4b4084c70ee 100644
--- a/docs/core/testing/mstest-analyzers/mstest0005.md
+++ b/docs/core/testing/mstest-analyzers/mstest0005.md
@@ -48,3 +48,22 @@ Ensure that the `TestContext` property matches the required layout described abo
## When to suppress warnings
Do not suppress a warning from this rule. Ignoring this rule will result in the `TestContext` not being injected by MSTest, thus resulting in `NullReferenceException` or inconsistent state when using the property.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0005
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0005
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0005.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0006.md b/docs/core/testing/mstest-analyzers/mstest0006.md
index d1ff170c79984..374671b1a5924 100644
--- a/docs/core/testing/mstest-analyzers/mstest0006.md
+++ b/docs/core/testing/mstest-analyzers/mstest0006.md
@@ -98,3 +98,22 @@ public class TestClass
}
}
```
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0006
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0006
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0006.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0007.md b/docs/core/testing/mstest-analyzers/mstest0007.md
index e18158f01b1a5..9cfb1cfc4f06f 100644
--- a/docs/core/testing/mstest-analyzers/mstest0007.md
+++ b/docs/core/testing/mstest-analyzers/mstest0007.md
@@ -48,3 +48,22 @@ To fix a violation of this rule, either convert the method on which you applied
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, your attributes will be ignored since they are designed for use only in a test context.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0007
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0007
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0007.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0008.md b/docs/core/testing/mstest-analyzers/mstest0008.md
index de551add8032b..0c3925e4e6982 100644
--- a/docs/core/testing/mstest-analyzers/mstest0008.md
+++ b/docs/core/testing/mstest-analyzers/mstest0008.md
@@ -50,3 +50,22 @@ Ensure that the method matches the layout described above.
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, flagged instances will be either skipped or result in runtime error.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0008
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0008
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0008.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0009.md b/docs/core/testing/mstest-analyzers/mstest0009.md
index 483a05a778c6d..2fa762d510cab 100644
--- a/docs/core/testing/mstest-analyzers/mstest0009.md
+++ b/docs/core/testing/mstest-analyzers/mstest0009.md
@@ -50,3 +50,22 @@ Ensure that the method matches the layout described above.
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, flagged instances will be either skipped or result in runtime error.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0009
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0009
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0009.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0010.md b/docs/core/testing/mstest-analyzers/mstest0010.md
index a0072763bf191..24ddfd0975fae 100644
--- a/docs/core/testing/mstest-analyzers/mstest0010.md
+++ b/docs/core/testing/mstest-analyzers/mstest0010.md
@@ -54,3 +54,22 @@ Ensure that the method matches the layout described above.
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, flagged instances will be either skipped or result in runtime error.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0010
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0010
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0010.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0011.md b/docs/core/testing/mstest-analyzers/mstest0011.md
index 469133b4613ed..6cf499e0038a5 100644
--- a/docs/core/testing/mstest-analyzers/mstest0011.md
+++ b/docs/core/testing/mstest-analyzers/mstest0011.md
@@ -54,3 +54,22 @@ Ensure that the method matches the layout described above.
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, flagged instances will be either skipped or result in runtime error.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0011
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0011
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0011.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0012.md b/docs/core/testing/mstest-analyzers/mstest0012.md
index cdbb95bce0d5d..941a329f7b900 100644
--- a/docs/core/testing/mstest-analyzers/mstest0012.md
+++ b/docs/core/testing/mstest-analyzers/mstest0012.md
@@ -56,3 +56,22 @@ Ensure that the method matches the layout described above.
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, flagged instances will be either skipped or result in runtime error.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0012
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0012
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0012.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0013.md b/docs/core/testing/mstest-analyzers/mstest0013.md
index fddeb725056cc..45fb4dec5698c 100644
--- a/docs/core/testing/mstest-analyzers/mstest0013.md
+++ b/docs/core/testing/mstest-analyzers/mstest0013.md
@@ -56,3 +56,22 @@ Ensure that the method matches the layout described above.
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, flagged instances will be either skipped or result in runtime error.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0013
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0013
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0013.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0014.md b/docs/core/testing/mstest-analyzers/mstest0014.md
index 2f840685a9c49..92fe67cc12733 100644
--- a/docs/core/testing/mstest-analyzers/mstest0014.md
+++ b/docs/core/testing/mstest-analyzers/mstest0014.md
@@ -43,3 +43,22 @@ Ensure that the `DataRow` instance matches the required layout described above.
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, flagged instances will be either skipped or result in runtime error.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0014
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0014
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0014.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0015.md b/docs/core/testing/mstest-analyzers/mstest0015.md
index c9383c9dfa72f..dbcce297f255d 100644
--- a/docs/core/testing/mstest-analyzers/mstest0015.md
+++ b/docs/core/testing/mstest-analyzers/mstest0015.md
@@ -39,3 +39,22 @@ Ensure that the test method isn't ignored.
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, test method will be ignored.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0015
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0015
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0015.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0016.md b/docs/core/testing/mstest-analyzers/mstest0016.md
index e9dad45a7d753..ee536eb904364 100644
--- a/docs/core/testing/mstest-analyzers/mstest0016.md
+++ b/docs/core/testing/mstest-analyzers/mstest0016.md
@@ -39,3 +39,22 @@ Ensure that the test class has a test method or is `static` and has methods attr
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, test class will be ignored.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0016
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0016
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0016.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0017.md b/docs/core/testing/mstest-analyzers/mstest0017.md
index ccfcde68608b6..7d9bbe17611be 100644
--- a/docs/core/testing/mstest-analyzers/mstest0017.md
+++ b/docs/core/testing/mstest-analyzers/mstest0017.md
@@ -46,3 +46,22 @@ Ensure that that `actual` and `expected`/`notExpected` arguments are passed in t
## When to suppress warnings
Do not suppress a warning from this rule as it would result to misleading output.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0017
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0017
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0017.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0018.md b/docs/core/testing/mstest-analyzers/mstest0018.md
index dadcb9b084f60..76be59f7b2f83 100644
--- a/docs/core/testing/mstest-analyzers/mstest0018.md
+++ b/docs/core/testing/mstest-analyzers/mstest0018.md
@@ -69,3 +69,22 @@ Ensure that the attribute matches the conditions described above.
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, flagged instances will be either skipped or result in runtime error.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0018
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0018
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0018.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0019.md b/docs/core/testing/mstest-analyzers/mstest0019.md
index 1f436eb4ede1c..dc79e84eab0e2 100644
--- a/docs/core/testing/mstest-analyzers/mstest0019.md
+++ b/docs/core/testing/mstest-analyzers/mstest0019.md
@@ -39,3 +39,22 @@ Replace the constructor call with a `[TestInitialize]` method.
## When to suppress warnings
You usually don't want to suppress warnings from this rule if you decided to opt-in for it.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0019
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0019
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0019.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0020.md b/docs/core/testing/mstest-analyzers/mstest0020.md
index 6e171312cb1fe..677defcc7c33d 100644
--- a/docs/core/testing/mstest-analyzers/mstest0020.md
+++ b/docs/core/testing/mstest-analyzers/mstest0020.md
@@ -39,3 +39,22 @@ Replace `[TestInitialize]` returning `void` by constructors.
## When to suppress warnings
You usually don't want to suppress warnings from this rule if you decided to opt-in for it.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0020
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0020
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0020.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0021.md b/docs/core/testing/mstest-analyzers/mstest0021.md
index d534184a7a661..4bf5f8c4b0093 100644
--- a/docs/core/testing/mstest-analyzers/mstest0021.md
+++ b/docs/core/testing/mstest-analyzers/mstest0021.md
@@ -39,3 +39,22 @@ Replace `[TestCleanup]` method by `Dispose` or `DisposeAsync` pattern.
## When to suppress warnings
You usually don't want to suppress warnings from this rule if you decided to opt-in for it.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0021
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0021
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0021.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0022.md b/docs/core/testing/mstest-analyzers/mstest0022.md
index 3a2d38999d579..0a2febdc1d0f6 100644
--- a/docs/core/testing/mstest-analyzers/mstest0022.md
+++ b/docs/core/testing/mstest-analyzers/mstest0022.md
@@ -39,3 +39,22 @@ Replace `Dispose` or `DisposeAsync` methods with `[TestCleanup]`.
## When to suppress warnings
You usually don't want to suppress warnings from this rule if you decided to opt-in for it.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0022
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0022
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0022.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0023.md b/docs/core/testing/mstest-analyzers/mstest0023.md
index edec4dcfca142..504b6586b718d 100644
--- a/docs/core/testing/mstest-analyzers/mstest0023.md
+++ b/docs/core/testing/mstest-analyzers/mstest0023.md
@@ -40,3 +40,22 @@ When negating argument in a `Assert.IsFalse` call, you should use `Assert.IsTrue
## When to suppress warnings
Do not suppress warnings from this rule.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0023
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0023
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0023.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0024.md b/docs/core/testing/mstest-analyzers/mstest0024.md
index 630be2f6edf0a..af6c9f123d740 100644
--- a/docs/core/testing/mstest-analyzers/mstest0024.md
+++ b/docs/core/testing/mstest-analyzers/mstest0024.md
@@ -39,3 +39,22 @@ Do not store the `[AssemblyInitialize]` or `[ClassInitialize]` `TestContext` par
## When to suppress warnings
You can suppress warnings from this rule if you are sure of the behavior does match what you want to do.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0024
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0024
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0024.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0025.md b/docs/core/testing/mstest-analyzers/mstest0025.md
index 3b0962cc0be2a..51209a0ec7677 100644
--- a/docs/core/testing/mstest-analyzers/mstest0025.md
+++ b/docs/core/testing/mstest-analyzers/mstest0025.md
@@ -45,3 +45,22 @@ Ensure that calls to `Assert.IsTrue`, `Assert.IsFalse`, `Assert.AreEqual`, `Asse
## When to suppress warnings
We do not recommend suppressing warnings from this rule.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0025
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0025
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0025.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0026.md b/docs/core/testing/mstest-analyzers/mstest0026.md
index e628053484674..d78166cd59f47 100644
--- a/docs/core/testing/mstest-analyzers/mstest0026.md
+++ b/docs/core/testing/mstest-analyzers/mstest0026.md
@@ -73,3 +73,22 @@ StringAssert.Contains(company.Address, "Brazil");
## When to suppress warnings
We do not recommend suppressing warnings from this rule.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0026
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0026
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0026.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0027.md b/docs/core/testing/mstest-analyzers/mstest0027.md
index f469bd0e2851c..0fc9641066503 100644
--- a/docs/core/testing/mstest-analyzers/mstest0027.md
+++ b/docs/core/testing/mstest-analyzers/mstest0027.md
@@ -26,4 +26,4 @@ Suppress the [VSTHRD200: Use Async suffix for async methods](https://github.com/
## When to disable suppressor
-You can disable this suppressor if you want to follow the `Async` suffix pattern also for your test methods.
+.NET suppressors cannot be disabled.
diff --git a/docs/core/testing/mstest-analyzers/mstest0028.md b/docs/core/testing/mstest-analyzers/mstest0028.md
index 7149dc15cecaa..efefead39967c 100644
--- a/docs/core/testing/mstest-analyzers/mstest0028.md
+++ b/docs/core/testing/mstest-analyzers/mstest0028.md
@@ -26,4 +26,4 @@ Suppress the [VSTHRD200: Use Async suffix for async methods](https://github.com/
## When to disable suppressor
-You can disable this suppressor if you want to follow the `Async` suffix pattern also for your test fixture methods.
+.NET suppressors cannot be disabled.
diff --git a/docs/core/testing/mstest-analyzers/mstest0029.md b/docs/core/testing/mstest-analyzers/mstest0029.md
index b18da31d74397..8f85b4f8bdc53 100644
--- a/docs/core/testing/mstest-analyzers/mstest0029.md
+++ b/docs/core/testing/mstest-analyzers/mstest0029.md
@@ -39,3 +39,22 @@ Ensure that the public method is a test method (marked with `[TestMethod]`).
## When to suppress warnings
Do not suppress a warning from this rule. If you ignore this rule, the public method won't be considered as a test method.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0029
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0029
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0029.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0030.md b/docs/core/testing/mstest-analyzers/mstest0030.md
index 0e8dd12750bfa..a9ca000a7e81f 100644
--- a/docs/core/testing/mstest-analyzers/mstest0030.md
+++ b/docs/core/testing/mstest-analyzers/mstest0030.md
@@ -39,3 +39,22 @@ A non-abstract class contains test methods should be marked with '[TestClass]'.
## When to suppress warnings
It's safe to suppress the diagnostic if you are sure that your class is being inherited and that the tests declared on this class should only be run in the context of subclasses. Nonetheless, we recommend marking the class as abstract.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0030
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0030
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0030.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0031.md b/docs/core/testing/mstest-analyzers/mstest0031.md
index 06605961fbebb..bcfca12544eb0 100644
--- a/docs/core/testing/mstest-analyzers/mstest0031.md
+++ b/docs/core/testing/mstest-analyzers/mstest0031.md
@@ -39,3 +39,22 @@ Remove or replace `System.ComponentModel.DescriptionAttribute` by `Microsoft.Vis
## When to suppress warnings
We don't recommend to suppress the diagnostic as the `System.ComponentModel.DescriptionAttribute` has no effect in the context of tests.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0031
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0031
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0031.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0032.md b/docs/core/testing/mstest-analyzers/mstest0032.md
index 687c7a2e3409e..cce0b1fc46cb9 100644
--- a/docs/core/testing/mstest-analyzers/mstest0032.md
+++ b/docs/core/testing/mstest-analyzers/mstest0032.md
@@ -39,3 +39,22 @@ Ensure that calls to `Assert.IsTrue`, `Assert.IsFalse`, `Assert.AreEqual`, `Asse
## When to suppress warnings
It's _not_ recommended to suppress warnings from this rule.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0032
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0032
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0032.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0033.md b/docs/core/testing/mstest-analyzers/mstest0033.md
index 3d585dbb5acba..05743403fffaf 100644
--- a/docs/core/testing/mstest-analyzers/mstest0033.md
+++ b/docs/core/testing/mstest-analyzers/mstest0033.md
@@ -26,4 +26,4 @@ Suppress the [CS8618: Non-nullable variable must contain a non-null value when e
## When to disable suppressor
-It's _not_ recommended to disable this suppressor.
+.NET suppressors cannot be disabled.
diff --git a/docs/core/testing/mstest-analyzers/mstest0034.md b/docs/core/testing/mstest-analyzers/mstest0034.md
index d2af3c4dbbde0..ff6d042ae6f2a 100644
--- a/docs/core/testing/mstest-analyzers/mstest0034.md
+++ b/docs/core/testing/mstest-analyzers/mstest0034.md
@@ -39,3 +39,22 @@ Use `ClassCleanupBehavior.EndOfClass` with the `[ClassCleanup]`.
## When to suppress warnings
It's _not_ recommended to suppress warnings from this rule as you can use instead `[AssemblyCleanup]`.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0034
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0034
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0034.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0035.md b/docs/core/testing/mstest-analyzers/mstest0035.md
index fc88e19ba0524..5799b725339e0 100644
--- a/docs/core/testing/mstest-analyzers/mstest0035.md
+++ b/docs/core/testing/mstest-analyzers/mstest0035.md
@@ -39,3 +39,22 @@ Ensure the attribute `[DeploymentItem]` is specified on a test class or a test m
## When to suppress warnings
It's _not_ recommended to suppress warnings from this rule as the `[DeploymentItem]` will be ignored.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0035
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0035
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0035.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0036.md b/docs/core/testing/mstest-analyzers/mstest0036.md
index e0a055466bc7e..c6f38fad5f3b2 100644
--- a/docs/core/testing/mstest-analyzers/mstest0036.md
+++ b/docs/core/testing/mstest-analyzers/mstest0036.md
@@ -39,3 +39,22 @@ Delete the shadowing member.
## When to suppress warnings
Don't suppress warnings from this rule as it could cause testing issues (such as NRE).
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0036
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0036
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0036.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/mstest-analyzers/mstest0037.md b/docs/core/testing/mstest-analyzers/mstest0037.md
index 6c37be8bc677e..d43323fe80205 100644
--- a/docs/core/testing/mstest-analyzers/mstest0037.md
+++ b/docs/core/testing/mstest-analyzers/mstest0037.md
@@ -57,3 +57,22 @@ Use the better alternative method.
## When to suppress warnings
If the assert is intended to verify the behavior of a user-defined operator, you can and should suppress the warning.
+
+## Suppress a warning
+
+If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
+
+```csharp
+#pragma warning disable MSTEST0037
+// The code that's violating the rule is on this line.
+#pragma warning restore MSTEST0037
+```
+
+To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md).
+
+```ini
+[*.{cs,vb}]
+dotnet_diagnostic.MSTEST0037.severity = none
+```
+
+For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md).
diff --git a/docs/core/testing/unit-testing-platform-extensions-code-coverage.md b/docs/core/testing/unit-testing-platform-extensions-code-coverage.md
index df69be8f11ece..afc2096569486 100644
--- a/docs/core/testing/unit-testing-platform-extensions-code-coverage.md
+++ b/docs/core/testing/unit-testing-platform-extensions-code-coverage.md
@@ -12,10 +12,6 @@ This article list and explains all `Microsoft Testing Platform` extensions relat
You can use the code coverage feature to determine what proportion of your project's code is being tested by coded tests such as unit tests. To effectively guard against bugs, your tests should exercise or *cover* a large proportion of your code.
-## Coverlet
-
-There's currently no Coverlet extension, but you can use [Coverlet .NET global tool](https://github.com/coverlet-coverage/coverlet#net-global-tool-guide-suffers-from-possible-known-issue).
-
## Microsoft code coverage
Microsoft Code Coverage analysis is possible for both managed (CLR) and unmanaged (native) code. Both static and dynamic instrumentation are supported. This extension is shipped as part of [Microsoft.Testing.Extensions.CodeCoverage](https://nuget.org/packages/Microsoft.Testing.Extensions.CodeCoverage) NuGet package.
@@ -39,3 +35,7 @@ Microsoft Code Coverage provides the following options:
| `--coverage-settings` | XML code coverage settings. |
For more information about the available options, see [settings](../additional-tools/dotnet-coverage.md#settings) and [samples](https://github.com/microsoft/codecoverage/tree/main/samples/Algorithms).
+
+## Coverlet
+
+There's currently no Coverlet extension, but you can use [Coverlet .NET global tool](https://github.com/coverlet-coverage/coverlet#net-global-tool-guide-suffers-from-possible-known-issue).
diff --git a/docs/core/testing/unit-testing-platform-integration-dotnet-test.md b/docs/core/testing/unit-testing-platform-integration-dotnet-test.md
index 6b3f57910dab5..c33265c649210 100644
--- a/docs/core/testing/unit-testing-platform-integration-dotnet-test.md
+++ b/docs/core/testing/unit-testing-platform-integration-dotnet-test.md
@@ -169,3 +169,6 @@ Or in project file:
```
+
+> [!IMPORTANT]
+> All examples above add properties like `EnableMSTestRunner`, `TestingPlatformDotnetTestSupport`, and `TestingPlatformCaptureOutput` in the csproj file. However, it's highly recommended that you set these properties in `Directory.Build.props`. That way, you don't have to add it to every test project file, and you don't risk introducing a new project that doesn't set these properties and end up with a solution where some projects are VSTest while others are Microsoft.Testing.Platform, which may not work correctly and is unsupported scenario.
diff --git a/docs/core/tools/dotnet-test.md b/docs/core/tools/dotnet-test.md
index 054b4f0f1976c..bc843d4739dfb 100644
--- a/docs/core/tools/dotnet-test.md
+++ b/docs/core/tools/dotnet-test.md
@@ -278,16 +278,16 @@ Where `Microsoft.NET.Test.Sdk` is the test host, `xunit` is the test framework.
dotnet test --logger trx
```
-- Run the tests in the project in the current directory, and generate a code coverage file (after installing [Coverlet](https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/VSTestIntegration.md) collectors integration):
+- Run the tests in the project in the current directory, and generate a code coverage file using [Microsoft Code Coverage](https://github.com/microsoft/codecoverage/blob/main/README.md):
```dotnetcli
- dotnet test --collect:"XPlat Code Coverage"
+ dotnet test --collect "Code Coverage"
```
-- Run the tests in the project in the current directory, and generate a code coverage file (Windows only):
+- Run the tests in the project in the current directory, and generate a code coverage file using [Coverlet](https://github.com/coverlet-coverage/coverlet/blob/master/README.md) (after installing [Coverlet](https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/VSTestIntegration.md) collectors integration):
```dotnetcli
- dotnet test --collect "Code Coverage"
+ dotnet test --collect:"XPlat Code Coverage"
```
- Run the tests in the project in the current directory, and log with detailed verbosity to the console:
diff --git a/docs/csharp/fundamentals/coding-style/coding-conventions.md b/docs/csharp/fundamentals/coding-style/coding-conventions.md
index 168dec7ba6a75..87fcd8265536d 100644
--- a/docs/csharp/fundamentals/coding-style/coding-conventions.md
+++ b/docs/csharp/fundamentals/coding-style/coding-conventions.md
@@ -1,7 +1,7 @@
---
title: ".NET Coding Conventions"
description: Learn about commonly used coding conventions in C#. Coding conventions create a consistent look to the code and facilitate copying, changing, and maintaining the code. This article also includes the docs repo coding guidelines
-ms.date: 07/27/2023
+ms.date: 01/15/2025
helpviewer_keyword:
- "coding conventions, C#"
- "Visual C#, coding conventions"
@@ -19,19 +19,19 @@ We chose our conventions based on the following goals:
1. *Adoption*: We aggressively update our samples to use new language features. That practice raises awareness of new features, and makes them more familiar to all C# developers.
> [!IMPORTANT]
-> These guidelines are used by Microsoft to develop samples and documentation. They were adopted from the [.NET Runtime, C# Coding Style](https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/coding-style.md) and [C# compiler (roslyn)](https://github.com/dotnet/roslyn/blob/main/CONTRIBUTING.md#csharp) guidelines. We chose those guidelines because they have been tested over several years of Open Source development. They've helped community members participate in the runtime and compiler projects. They are meant to be an example of common C# conventions, and not an authoritative list (see [Framework Design Guidelines](../../../standard/design-guidelines/index.md) for that).
+> These guidelines are used by Microsoft to develop samples and documentation. They were adopted from the [.NET Runtime, C# Coding Style](https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/coding-style.md) and [C# compiler (roslyn)](https://github.com/dotnet/roslyn/blob/main/CONTRIBUTING.md#csharp) guidelines. We chose those guidelines because of their adoption over several years of Open Source development. These guidelines help community members participate in the runtime and compiler projects. They're meant to be an example of common C# conventions, and not an authoritative list (see [Framework Design Guidelines](../../../standard/design-guidelines/index.md) for detailed guidelines).
>
> The *teaching* and *adoption* goals are why the docs coding convention differs from the runtime and compiler conventions. Both the runtime and compiler have strict performance metrics for hot paths. Many other applications don't. Our *teaching* goal mandates that we don't prohibit any construct. Instead, samples show when constructs should be used. We update samples more aggressively than most production applications do. Our *adoption* goal mandates that we show code you should write today, even when code written last year doesn't need changes.
-This article explains our guidelines. The guidelines have evolved over time, and you'll find samples that don't follow our guidelines. We welcome PRs that bring those samples into compliance, or issues that draw our attention to samples we should update. Our guidelines are Open Source and we welcome PRs and issues. However, if your submission would change these recommendations, open an issue for discussion first. You're welcome to use our guidelines, or adapt them to your needs.
+This article explains our guidelines. The guidelines evolve over time, and you'll find samples that don't follow our guidelines. We welcome PRs that bring those samples into compliance, or issues that draw our attention to samples we should update. Our guidelines are Open Source and we welcome PRs and issues. However, if your submission would change these recommendations, open an issue for discussion first. You're welcome to use our guidelines, or adapt them to your needs.
## Tools and analyzers
-Tools can help your team enforce your conventions. You can enable [code analysis](../../../fundamentals/code-analysis/overview.md) to enforce the rules you prefer. You can also create an [editorconfig](/visualstudio/ide/create-portable-custom-editor-options) so that Visual Studio automatically enforces your style guidelines. As a starting point, you can copy the [dotnet/docs repo's file](https://github.com/dotnet/docs/blob/main/.editorconfig) to use our style.
+Tools can help your team enforce your conventions. You can enable [code analysis](../../../fundamentals/code-analysis/overview.md) to enforce the rules you prefer. You can also create an [editorconfig](/visualstudio/ide/create-portable-custom-editor-options) so that Visual Studio automatically enforces your style guidelines. As a starting point, you can copy the [`dotnet/docs` *.editorconfig*](https://github.com/dotnet/docs/blob/main/.editorconfig) to use our style.
-These tools make it easier for your team to adopt your preferred guidelines. Visual Studio applies the rules in all `.editorconfig` files in scope to format your code. You can use multiple configurations to enforce corporate-wide conventions, team conventions, and even granular project conventions.
+These tools make it easier for your team to adopt your preferred guidelines. Visual Studio applies the rules in all *.editorconfig* files in scope to format your code. You can use multiple configurations to enforce corporate-wide conventions, team conventions, and even granular project conventions.
-Code analysis produces warnings and diagnostics when the enabled rules are violated. You configure the rules you want applied to your project. Then, each CI build notifies developers when they violate any of the rules.
+Code analysis produces warnings and diagnostics when it detects rule violations. You configure the rules you want applied to your project. Then, each CI build notifies developers when they violate any of the rules.
### Diagnostic IDs
@@ -42,13 +42,13 @@ Code analysis produces warnings and diagnostics when the enabled rules are viola
The following sections describe practices that the .NET docs team follows to prepare code examples and samples. In general, follow these practices:
- Utilize modern language features and C# versions whenever possible.
-- Avoid obsolete or outdated language constructs.
-- Only catch exceptions that can be properly handled; avoid catching generic exceptions.
+- Avoid outdated language constructs.
+- Only catch exceptions that can be properly handled; avoid catching general exceptions. For example, sample code shouldn't catch the type without an exception filter.
- Use specific exception types to provide meaningful error messages.
- Use LINQ queries and methods for collection manipulation to improve code readability.
- Use asynchronous programming with async and await for I/O-bound operations.
- Be cautious of deadlocks and use when appropriate.
-- Use the language keywords for data types instead of the runtime types. For example, use `string` instead of , or `int` instead of .
+- Use the language keywords for data types instead of the runtime types. For example, use `string` instead of , or `int` instead of . This recommendation includes using the types `nint` and `nuint`.
- Use `int` rather than unsigned types. The use of `int` is common throughout C#, and it's easier to interact with other libraries when you use `int`. Exceptions are for documentation specific to unsigned data types.
- Use `var` only when a reader can infer the type from the expression. Readers view our samples on the docs platform. They don't have hover or tool tips that display the type of variables.
- Write code with clarity and simplicity in mind.
@@ -66,15 +66,30 @@ More specific guidelines follow.
:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet7":::
-### Arrays
+- Prefer raw string literals to escape sequences or verbatim strings.
-- Use the concise syntax when you initialize arrays on the declaration line. In the following example, you can't use `var` instead of `string[]`.
+ :::code language="csharp" source="./snippets/coding-conventions/program.cs" id="rawStringLiterals":::
-:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet13a":::
+- Use the expression-based string interpolation rather than positional string interpolation.
-- If you use explicit instantiation, you can use `var`.
+ :::code language="csharp" source="./snippets/coding-conventions/program.cs" id="interpolatedStrings":::
-:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet13b":::
+### Constructors and initialization
+
+- Use Pascal case for primary constructor parameters on record types:
+
+ :::code language="csharp" source="./snippets/coding-conventions/program.cs" id="PrimaryRecord":::
+
+- Use camel case for primary constructor parameters on class and struct types.
+- Use `required` properties instead of constructors to force initialization of property values:
+
+ :::code language="csharp" source="./snippets/coding-conventions/program.cs" id="PrimaryClass":::
+
+### Arrays and collections
+
+- Use collection expressions to initialize all collection types:
+
+:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet13":::
### Delegates
@@ -128,7 +143,7 @@ If the divisor is 0, the second clause in the `if` statement would cause a run-t
### `new` operator
-- Use one of the concise forms of object instantiation, as shown in the following declarations.
+- Use one of the concise forms of object instantiation when the variable type matches the object type, as shown in the following declarations. This form isn't valid when the variable is an interface type, or a base class of the runtime type.
:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet19":::
@@ -160,7 +175,7 @@ The lambda expression shortens the following traditional definition.
### Static members
-Call [static](../../language-reference/keywords/static.md) members by using the class name: *ClassName.StaticMember*. This practice makes code more readable by making static access clear. Don't qualify a static member defined in a base class with the name of a derived class. While that code compiles, the code readability is misleading, and the code may break in the future if you add a static member with the same name to the derived class.
+Call [static](../../language-reference/keywords/static.md) members by using the class name: *ClassName.StaticMember*. This practice makes code more readable by making static access clear. Don't qualify a static member defined in a base class with the name of a derived class. While that code compiles, the code readability is misleading, and the code might break in the future if you add a static member with the same name to the derived class.
### LINQ queries
@@ -172,7 +187,7 @@ Call [static](../../language-reference/keywords/static.md) members by using the
:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet26":::
-- Rename properties when the property names in the result would be ambiguous. For example, if your query returns a customer name and a distributor ID, instead of leaving them as `Name` and `ID` in the result, rename them to clarify that `Name` is the name of a customer, and `ID` is the ID of a distributor.
+- Rename properties when the property names in the result would be ambiguous. For example, if your query returns a customer name and a distributor name, instead of leaving them as a form of `Name` in the result, rename them to clarify `CustomerName` is the name of a customer, and `DistributorName` is the name of a distributor.
:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet27":::
@@ -186,7 +201,7 @@ Call [static](../../language-reference/keywords/static.md) members by using the
:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet29":::
-- Use multiple `from` clauses instead of a [`join`](../../language-reference/keywords/join-clause.md) clause to access inner collections. For example, a collection of `Student` objects might each contain a collection of test scores. When the following query is executed, it returns each score that is over 90, along with the last name of the student who received the score.
+- Access inner collections with multiple `from` clauses instead of a [`join`](../../language-reference/keywords/join-clause.md) clause. For example, a collection of `Student` objects might each contain a collection of test scores. When the following query is executed, it returns each score that is over 90, along with the family name of the student who received the score.
:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet30":::
@@ -196,7 +211,7 @@ Call [static](../../language-reference/keywords/static.md) members by using the
:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet8":::
-- Don't use [var](../../language-reference/statements/declarations.md#implicitly-typed-local-variables) when the type isn't apparent from the right side of the assignment. Don't assume the type is clear from a method name. A variable type is considered clear if it's a `new` operator, an explicit cast or assignment to a literal value.
+- Don't use [var](../../language-reference/statements/declarations.md#implicitly-typed-local-variables) when the type isn't apparent from the right side of the assignment. Don't assume the type is clear from a method name. A variable type is considered clear if it's a `new` operator, an explicit cast, or assignment to a literal value.
:::code language="csharp" source="./snippets/coding-conventions/program.cs" id="Snippet9":::
@@ -221,10 +236,18 @@ Call [static](../../language-reference/keywords/static.md) members by using the
- use implicit type for the result sequences in LINQ queries. The section on [LINQ](#linq-queries) explains that many LINQ queries result in anonymous types where implicit types must be used. Other queries result in nested generic types where `var` is more readable.
> [!NOTE]
- > Be careful not to accidentally change a type of an element of the iterable collection. For example, it is easy to switch from to in a `foreach` statement, which changes the execution of a query.
+ > Be careful not to accidentally change a type of an element of the iterable collection. For example, it's easy to switch from to in a `foreach` statement, which changes the execution of a query.
Some of our samples explain the *natural type* of an expression. Those samples must use `var` so that the compiler picks the natural type. Even though those examples are less obvious, the use of `var` is required for the sample. The text should explain the behavior.
+### File scoped namespace declarations
+
+Most code files declare a single namespace. Therefore, our examples should use the file scoped namespace declarations:
+
+```csharp
+namespace MySampleCode;
+```
+
### Place the using directives outside the namespace declaration
When a `using` directive is outside a namespace declaration, that imported namespace is its fully qualified name. The fully qualified name is clearer. When the `using` directive is inside the namespace, it could be either relative to that namespace, or its fully qualified name.
@@ -272,7 +295,7 @@ And it compiles today. And tomorrow. But then sometime next week the preceding (
- error CS0103: The name 'WaitUntil' does not exist in the current context
```
-One of the dependencies has introduced this class in a namespace then ends with `.Azure`:
+One of the dependencies introduced this class in a namespace then ends with `.Azure`:
```csharp
namespace CoolStuff.Azure
@@ -315,14 +338,14 @@ In general, use the following format for code samples:
- Use four spaces for indentation. Don't use tabs.
- Align code consistently to improve readability.
- Limit lines to 65 characters to enhance code readability on docs, especially on mobile screens.
-- Break long statements into multiple lines to improve clarity.
+- Improve clarity and user experience by breaking long statements into multiple lines.
- Use the "Allman" style for braces: open and closing brace its own new line. Braces line up with current indentation level.
- Line breaks should occur before binary operators, if necessary.
### Comment style
- Use single-line comments (`//`) for brief explanations.
-- Avoid multi-line comments (`/* */`) for longer explanations. Comments in the code samples aren't localized. That means explanations embedded in the code will not be translated. Longer, explanatory text should be placed in the companion article, so that it can be localized.
+- Avoid multi-line comments (`/* */`) for longer explanations. Comments in the code samples aren't localized. That means explanations embedded in the code aren't translated. Longer, explanatory text should be placed in the companion article, so that it can be localized.
- For describing methods, classes, fields, and all public members use [XML comments](../../language-reference/xmldoc/index.md).
- Place the comment on a separate line, not at the end of a line of code.
- Begin comment text with an uppercase letter.
diff --git a/docs/csharp/fundamentals/coding-style/snippets/coding-conventions/coding-conventions.csproj b/docs/csharp/fundamentals/coding-style/snippets/coding-conventions/coding-conventions.csproj
index ea0eaf187a84a..10875a126b52f 100644
--- a/docs/csharp/fundamentals/coding-style/snippets/coding-conventions/coding-conventions.csproj
+++ b/docs/csharp/fundamentals/coding-style/snippets/coding-conventions/coding-conventions.csproj
@@ -2,7 +2,8 @@
WinExe
- net8.0-windows
+ enable
+ net9.0-windows
enable
enable
Coding_Conventions_Examples.Program
diff --git a/docs/csharp/fundamentals/coding-style/snippets/coding-conventions/program.cs b/docs/csharp/fundamentals/coding-style/snippets/coding-conventions/program.cs
index a514e32fd7a67..10611e00813fb 100644
--- a/docs/csharp/fundamentals/coding-style/snippets/coding-conventions/program.cs
+++ b/docs/csharp/fundamentals/coding-style/snippets/coding-conventions/program.cs
@@ -61,16 +61,18 @@ static void Main(string[] args)
// Save snippet 4 and 5 for possible additions in program structure.
- Name[] nameList = {new Name { FirstName = "Anderson", LastName = "Redmond" },
- new Name { FirstName = "Jones", LastName = "Seattle" },
- new Name { FirstName = "Anderson", LastName = "Redmond" }};
+ Name[] nameList = [
+ new Name { FirstName = "Anderson", LastName = "Redmond" },
+ new Name { FirstName = "Jones", LastName = "Seattle" },
+ new Name { FirstName = "Anderson", LastName = "Redmond" }
+ ];
int n = 0;
//
string displayName = $"{nameList[n].LastName}, {nameList[n].FirstName}";
//
- Console.WriteLine("{0}, {1}", nameList[n].LastName, nameList[n].FirstName);
+ Console.WriteLine($"{nameList[n].LastName}, {nameList[n].FirstName}");
Console.WriteLine(nameList[n].LastName + ", " + nameList[n].FirstName);
//
@@ -123,12 +125,9 @@ static void Main(string[] args)
Console.WriteLine();
//
- //
- string[] vowels1 = { "a", "e", "i", "o", "u" };
- //
- //
- var vowels2 = new string[] { "a", "e", "i", "o", "u" };
- //
+ //
+ string[] vowels = [ "a", "e", "i", "o", "u" ];
+ //
//
Del exampleDel2 = DelMethod;
@@ -152,10 +151,7 @@ static void Main(string[] args)
}
finally
{
- if (bodyStyle != null)
- {
- ((IDisposable)bodyStyle).Dispose();
- }
+ bodyStyle?.Dispose();
}
//
//
@@ -214,20 +210,14 @@ static void Main(string[] args)
ExampleClass.totalInstances = 1;
- var customers = new List
- {
- new Customer { Name = "Jones", ID = 432, City = "Redmond" }
- };
+ List Customers = [ new Customer { Name = "Jones", ID = 432, City = "Redmond" } ];
// Check shop name to use this.
- var distributors = new List
- {
- new Distributor { Name = "ShopSmart", ID = 11302, City = "Redmond" }
- };
+ List Distributors = [ new Distributor { Name = "ShopSmart", ID = 11302, City = "Redmond" } ];
//
//
- var seattleCustomers = from customer in customers
+ var seattleCustomers = from customer in Customers
//
where customer.City == "Seattle"
select customer.Name;
@@ -235,20 +225,20 @@ static void Main(string[] args)
//
var localDistributors =
- from customer in customers
- join distributor in distributors on customer.City equals distributor.City
+ from customer in Customers
+ join distributor in Distributors on customer.City equals distributor.City
select new { Customer = customer, Distributor = distributor };
//
//
var localDistributors2 =
- from customer in customers
- join distributor in distributors on customer.City equals distributor.City
- select new { CustomerName = customer.Name, DistributorID = distributor.ID };
+ from customer in Customers
+ join distributor in Distributors on customer.City equals distributor.City
+ select new { CustomerName = customer.Name, DistributorName = distributor.Name };
//
//
- var seattleCustomers2 = from customer in customers
+ var seattleCustomers2 = from customer in Customers
where customer.City == "Seattle"
orderby customer.Name
select customer;
@@ -257,13 +247,13 @@ orderby customer.Name
// #30 is in class CompoundFrom
var customerDistributorNames =
- from customer in customers
- join distributor in distributors on customer.City equals distributor.City
+ from customer in Customers
+ join distributor in Distributors on customer.City equals distributor.City
select new { CustomerName = customer.Name, DistributorID = distributor.ID };
var customerDistributorNames2 =
- from customer in customers
- from distributor in distributors
+ from customer in Customers
+ from distributor in Distributors
where customer.City == distributor.City
select new { CustomerName = customer.Name, DistributorID = distributor.ID };
@@ -335,20 +325,14 @@ public static int IncrementTotal()
return totalInstances;
}
- public static int ResultSoFar()
- {
- return 0;
- }
+ public static int ResultSoFar() => 0;
}
class BaseClass
{
protected static int totalInstances;
- static BaseClass()
- {
- totalInstances = 0;
- }
+ static BaseClass() => totalInstances = 0;
public static int IncrementTotal()
{
@@ -367,7 +351,7 @@ class CompoundFrom
public class Student
{
public string? LastName { get; set; }
- public List? Scores { get; set; }
+ public ICollection Scores { get; set; } = default!;
}
static void Main()
@@ -375,32 +359,37 @@ static void Main()
// Use a collection initializer to create the data source. Note that
// each element in the list contains an inner sequence of scores.
- List students = new List
- {
- new Student {LastName="Omelchenko", Scores= new List {97, 72, 81, 60}},
- new Student {LastName="O'Donnell", Scores= new List {75, 84, 91, 39}},
- new Student {LastName="Mortensen", Scores= new List {88, 94, 65, 85}},
- new Student {LastName="Garcia", Scores= new List {97, 89, 85, 82}},
- new Student {LastName="Beebe", Scores= new List {35, 72, 91, 70}}
- };
+ List students = [
+ new Student {LastName="Omelchenko", Scores = [97, 72, 81, 60]},
+ new Student {LastName="O'Donnell", Scores = [75, 84, 91, 39]},
+ new Student {LastName="Mortensen", Scores = [88, 94, 65, 85]},
+ new Student {LastName="Garcia", Scores = [97, 89, 85, 82]},
+ new Student {LastName="Beebe", Scores = [35, 72, 91, 70]}
+ ];
//
var scoreQuery = from student in students
- from score in student.Scores!
+ from score in student.Scores
where score > 90
select new { Last = student.LastName, score };
//
+ //
// Execute the queries.
Console.WriteLine("scoreQuery:");
foreach (var student in scoreQuery)
{
- Console.WriteLine("{0} Score: {1}", student.Last, student.score);
+ Console.WriteLine($"{student.Last} Score: {student.score}");
}
-
- // Keep the console window open in debug mode.
- Console.WriteLine("Press any key to exit.");
- Console.ReadKey();
+ //
+
+ //
+ var message = """
+ This is a long message that spans across multiple lines.
+ It uses raw string literals. This means we can
+ also include characters like \n and \t without escaping them.
+ """;
+ //
}
}
}
@@ -459,7 +448,7 @@ public class List { /*...*/ }
//
//
- public int IComparer() { return 0; }
+ public int IComparer() => 0;
public delegate bool Predicate(T item);
public struct Nullable where T : struct { /*...*/ }
//
@@ -475,3 +464,22 @@ public interface ISessionChannel
}
}//WrapParameters
}
+
+namespace Constructors
+{
+ //
+ public record Person(string FirstName, string LastName);
+ //
+
+ //
+ public class LabelledContainer(string label)
+ {
+ public string Label { get; } = label;
+ public required T Contents
+ {
+ get;
+ init;
+ }
+ }
+ //
+}
diff --git a/docs/csharp/language-reference/preprocessor-directives.md b/docs/csharp/language-reference/preprocessor-directives.md
index 3a79013cec760..c136e05808a10 100644
--- a/docs/csharp/language-reference/preprocessor-directives.md
+++ b/docs/csharp/language-reference/preprocessor-directives.md
@@ -1,7 +1,7 @@
---
description: "Learn the different C# preprocessor directives that control conditional compilation, warnings, nullable analysis, and more"
title: "Preprocessor directives"
-ms.date: 11/22/2024
+ms.date: 01/14/2025
f1_keywords:
- "cs.preprocessor"
- "#nullable"
@@ -45,21 +45,21 @@ Although the compiler doesn't have a separate preprocessor, the directives descr
## Nullable context
-The `#nullable` preprocessor directive sets the *nullable annotation context* and *nullable warning context*. This directive controls whether nullable annotations have effect, and whether nullability warnings are given. Each context is either *disabled* or *enabled*.
+The `#nullable` preprocessor directive sets the *annotations* and *warning* flags in the *nullable context*. This directive controls whether nullable annotations have effect, and whether nullability warnings are given. Each flag is either *disabled* or *enabled*.
-Both contexts can be specified at the project level (outside of C# source code) adding the [`Nullable`](./compiler-options/language.md#nullable) element to the `PropertyGroup` element. The `#nullable` directive controls the annotation and warning contexts and takes precedence over the project-level settings. A directive sets the context(s) it controls until another directive overrides it, or until the end of the source file.
+Both contexts can be specified at the project level (outside of C# source code) adding the [`Nullable`](./compiler-options/language.md#nullable) element to the `PropertyGroup` element. The `#nullable` directive controls the annotation and warning flags and takes precedence over the project-level settings. A directive sets the flag it controls until another directive overrides it, or until the end of the source file.
The effect of the directives is as follows:
-- `#nullable disable`: Sets the nullable annotation and warning contexts to *disabled*.
-- `#nullable enable`: Sets the nullable annotation and warning contexts to *enabled*.
-- `#nullable restore`: Restores the nullable annotation and warning contexts to project settings.
-- `#nullable disable annotations`: Sets the nullable annotation context to *disabled*.
-- `#nullable enable annotations`: Sets the nullable annotation context to *enabled*.
-- `#nullable restore annotations`: Restores the nullable annotation context to project settings.
-- `#nullable disable warnings`: Sets the nullable warning context to *disabled*.
-- `#nullable enable warnings`: Sets the nullable warning context to *enabled*.
-- `#nullable restore warnings`: Restores the nullable warning context to project settings.
+- `#nullable disable`: Sets the nullable context *disabled*.
+- `#nullable enable`: Sets the nullable context *enabled*.
+- `#nullable restore`: Restores the nullable context to project settings.
+- `#nullable disable annotations`: Sets the annotations flag in the nullable context to *disabled*.
+- `#nullable enable annotations`: Sets the annotations flag in the nullable context to *enabled*.
+- `#nullable restore annotations`: Restores the annotations flag in the nullable context to project settings.
+- `#nullable disable warnings`: Sets the warning flag in the nullable context to *disabled*.
+- `#nullable enable warnings`: Sets the warning flag in the nullable context to *enabled*.
+- `#nullable restore warnings`: Restores the warning flag in the nullable context to project settings.
## Conditional compilation
@@ -70,7 +70,16 @@ You use four preprocessor directives to control conditional compilation:
- `#else`: Closes the preceding conditional compilation and opens a new conditional compilation if the previous specified symbol isn't defined.
- `#endif`: Closes the preceding conditional compilation.
-The C# compiler compiles the code between the `#if` directive and `#endif` directive only if the specified symbol is defined, or not defined when the `!` not operator is used. Unlike C and C++, a numeric value to a symbol can't be assigned. The `#if` statement in C# is Boolean and only tests whether the symbol has been defined or not. For example, the following code is compiled when `DEBUG` is defined:
+The build system is also aware of predefined preprocessor symbols representing different [target frameworks](../../standard/frameworks.md) in SDK-style projects. They're useful when creating applications that can target more than one .NET version.
+
+[!INCLUDE [Preprocessor symbols](~/includes/preprocessor-symbols.md)]
+
+> [!NOTE]
+> For traditional, non-SDK-style projects, you have to manually configure the conditional compilation symbols for the different target frameworks in Visual Studio via the project's properties pages.
+
+Other predefined symbols include the `DEBUG` and `TRACE` constants. You can override the values set for the project using `#define`. The DEBUG symbol, for example, is automatically set depending on your build configuration properties ("Debug" or "Release" mode).
+
+The C# compiler compiles the code between the `#if` directive and `#endif` directive only if the specified symbol is defined, or not defined when the `!` not operator is used. Unlike C and C++, a numeric value to a symbol can't be assigned. The `#if` statement in C# is Boolean and only tests whether the symbol is defined or not. For example, the following code is compiled when `DEBUG` is defined:
```csharp
#if DEBUG
@@ -86,9 +95,9 @@ The following code is compiled when `MYTEST` is **not** defined:
#endif
```
-You can use the operators [`==` (equality)](operators/equality-operators.md#equality-operator-) and [`!=` (inequality)](operators/equality-operators.md#inequality-operator-) to test for the [`bool`](builtin-types/bool.md) values `true` or `false`. `true` means the symbol is defined. The statement `#if DEBUG` has the same meaning as `#if (DEBUG == true)`. You can use the [`&&` (and)](operators/boolean-logical-operators.md#conditional-logical-and-operator-), [`||` (or)](operators/boolean-logical-operators.md#conditional-logical-or-operator-), and [`!` (not)](operators/boolean-logical-operators.md#logical-negation-operator-) operators to evaluate whether multiple symbols have been defined. You can also group symbols and operators with parentheses.
+You can use the operators [`==` (equality)](operators/equality-operators.md#equality-operator-) and [`!=` (inequality)](operators/equality-operators.md#inequality-operator-) to test for the [`bool`](builtin-types/bool.md) values `true` or `false`. `true` means the symbol is defined. The statement `#if DEBUG` has the same meaning as `#if (DEBUG == true)`. You can use the [`&&` (and)](operators/boolean-logical-operators.md#conditional-logical-and-operator-), [`||` (or)](operators/boolean-logical-operators.md#conditional-logical-or-operator-), and [`!` (not)](operators/boolean-logical-operators.md#logical-negation-operator-) operators to evaluate whether multiple symbols are defined. You can also group symbols and operators with parentheses.
-The following is a complex directive that allows your code to take advantage of newer .NET features while remaining backward compatible. For example, imagine that you're using a NuGet package in your code, but the package only supports .NET 6 and up, as well as .NET Standard 2.0 and up:
+The following example shows a complex directive that allows your code to take advantage of newer .NET features while remaining backward compatible. For example, imagine that you're using a NuGet package in your code, but the package only supports .NET 6 and up, as well as .NET Standard 2.0 and up:
```csharp
#if (NET6_0_OR_GREATER || NETSTANDARD2_0_OR_GREATER)
@@ -100,9 +109,7 @@ The following is a complex directive that allows your code to take advantage of
`#if`, along with the `#else`, `#elif`, `#endif`, `#define`, and `#undef` directives, lets you include or exclude code based on the existence of one or more symbols. Conditional compilation can be useful when compiling code for a debug build or when compiling for a specific configuration.
-A conditional directive beginning with an `#if` directive must explicitly be terminated with an `#endif` directive. `#define` lets you define a symbol. By using the symbol as the expression passed to the `#if` directive, the expression evaluates to `true`. You can also define a symbol with the [**DefineConstants**](compiler-options/language.md#defineconstants) compiler option. You can undefine a symbol with `#undef`. The scope of a symbol created with `#define` is the file in which it was defined. A symbol that you define with **DefineConstants** or with `#define` doesn't conflict with a variable of the same name. That is, a variable name shouldn't be passed to a preprocessor directive, and a symbol can only be evaluated by a preprocessor directive.
-
-`#elif` lets you create a compound conditional directive. The `#elif` expression will be evaluated if neither the preceding `#if` nor any preceding, optional, `#elif` directive expressions evaluate to `true`. If an `#elif` expression evaluates to `true`, the compiler evaluates all the code between the `#elif` and the next conditional directive. For example:
+`#elif` lets you create a compound conditional directive. The `#elif` expression is evaluated if neither the preceding `#if` nor any preceding, optional, `#elif` directive expressions evaluate to `true`. If an `#elif` expression evaluates to `true`, the compiler evaluates all the code between the `#elif` and the next conditional directive. For example:
```csharp
#define VC7
@@ -118,15 +125,6 @@ A conditional directive beginning with an `#if` directive must explicitly be ter
`#endif` specifies the end of a conditional directive, which began with the `#if` directive.
-The build system is also aware of predefined preprocessor symbols representing different [target frameworks](../../standard/frameworks.md) in SDK-style projects. They're useful when creating applications that can target more than one .NET version.
-
-[!INCLUDE [Preprocessor symbols](~/includes/preprocessor-symbols.md)]
-
-> [!NOTE]
-> For traditional, non-SDK-style projects, you have to manually configure the conditional compilation symbols for the different target frameworks in Visual Studio via the project's properties pages.
-
-Other predefined symbols include the `DEBUG` and `TRACE` constants. You can override the values set for the project using `#define`. The DEBUG symbol, for example, is automatically set depending on your build configuration properties ("Debug" or "Release" mode).
-
The following example shows you how to define a `MYTEST` symbol on a file and then test the values of the `MYTEST` and `DEBUG` symbols. The output of this example depends on whether you built the project on **Debug** or **Release** configuration mode.
```csharp
@@ -173,7 +171,7 @@ You use the following two preprocessor directives to define or undefine symbols
- `#define`: Define a symbol.
- `#undef`: Undefine a symbol.
-You use `#define` to define a symbol. When you use the symbol as the expression that's passed to the `#if` directive, the expression will evaluate to `true`, as the following example shows:
+You use `#define` to define a symbol. When you use the symbol as the expression passed to the `#if` directive, the expression evaluates to `true`, as the following example shows:
```csharp
#define VERBOSE
@@ -235,7 +233,7 @@ You instruct the compiler to generate user-defined compiler errors and warnings,
`#line` lets you modify the compiler's line numbering and (optionally) the file name output for errors and warnings.
-The following example shows how to report two warnings associated with line numbers. The `#line 200` directive forces the next line's number to be 200 (although the default is #6), and until the next `#line` directive, the filename will be reported as "Special". The `#line default` directive returns the line numbering to its default numbering, which counts the lines that were renumbered by the previous directive.
+The following example shows how to report two warnings associated with line numbers. The `#line 200` directive forces the next line's number to be 200 (although the default is #6), and until the next `#line` directive, the filename will be reported as "Special." The `#line default` directive returns the line numbering to its default numbering, which counts the lines renumbered by the previous directive.
```csharp
class MainClass
@@ -268,11 +266,11 @@ MainClass.cs(13,16): warning CS0168: The variable 'd' is declared but never used
The `#line` directive might be used in an automated, intermediate step in the build process. For example, if lines were removed from the original source code file, but you still wanted the compiler to generate output based on the original line numbering in the file, you could remove lines and then simulate the original line numbering with `#line`.
-The `#line hidden` directive hides the successive lines from the debugger, such that when the developer steps through the code, any lines between a `#line hidden` and the next `#line` directive (assuming that it isn't another `#line hidden` directive) will be stepped over. This option can also be used to allow ASP.NET to differentiate between user-defined and machine-generated code. Although ASP.NET is the primary consumer of this feature, it's likely that more source generators will make use of it.
+The `#line hidden` directive hides the successive lines from the debugger, such that when the developer steps through the code, any lines between a `#line hidden` and the next `#line` directive (assuming that it isn't another `#line hidden` directive) will be stepped over. This option can also be used to allow ASP.NET to differentiate between user-defined and machine-generated code. Although ASP.NET is the primary consumer of this feature, it's likely that more source generators make use of it.
-A `#line hidden` directive doesn't affect file names or line numbers in error reporting. That is, if the compiler finds an error in a hidden block, the compiler will report the current file name and line number of the error.
+A `#line hidden` directive doesn't affect file names or line numbers in error reporting. That is, if the compiler finds an error in a hidden block, the compiler reports the current file name and line number of the error.
-The `#line filename` directive specifies the file name you want to appear in the compiler output. By default, the actual name of the source code file is used. The file name must be in double quotation marks ("") and must be preceded by a line number.
+The `#line filename` directive specifies the file name you want to appear in the compiler output. By default, the actual name of the source code file is used. The file name must be in double quotation marks ("") and must follow a line number.
You can use a new form of the `#line` directive:
@@ -283,9 +281,9 @@ You can use a new form of the `#line` directive:
The components of this form are:
-- `(1, 1)`: The start line and column for the first character on the line that follows the directive. In this example, the next line would be reported as line 1, column 1.
+- `(1, 1)`: The start line and column for the first character on the line following the directive. In this example, the next line would be reported as line 1, column 1.
- `(5, 60)`: The end line and column for the marked region.
-- `10`: The column offset for the `#line` directive to take effect. In this example, the 10th column would be reported as column one. That's where the declaration `int b = 0;` begins. This field is optional. If omitted, the directive takes effect on the first column.
+- `10`: The column offset for the `#line` directive to take effect. In this example, the 10th column would be reported as column one. The declaration `int b = 0;` begins at that column. This field is optional. If omitted, the directive takes effect on the first column.
- `"partial-class.cs"`: The name of the output file.
The preceding example would generate the following warning:
@@ -296,14 +294,14 @@ partial-class.cs(1,5,1,6): warning CS0219: The variable 'b' is assigned but its
After remapping, the variable, `b`, is on the first line, at character six, of the file `partial-class.cs`.
-Domain-specific languages (DSLs) typically use this format to provide a better mapping from the source file to the generated C# output. The most common use of this extended `#line` directive is to re-map warnings or errors that appear in a generated file to the original source. For example, consider this razor page:
+Domain-specific languages (DSLs) typically use this format to provide a better mapping from the source file to the generated C# output. The most common use of this extended `#line` directive is to remap warnings or errors that appear in a generated file to the original source. For example, consider this razor page:
```razor
@page "/"
Time: @DateTime.NowAndThen
```
-The property `DateTime.Now` was typed incorrectly as `DateTime.NowAndThen`. The generated C# for this razor snippet looks like the following, in `page.g.cs`:
+The property `DateTime.Now` was typed incorrectly as `DateTime.NowAndThen`. The generated C# for this razor snippet looks like the following, in `page.g.cs`:
```csharp
_builder.Add("Time: ");
@@ -317,13 +315,13 @@ The compiler output for the preceding snippet is:
page.razor(2, 2, 2, 27)error CS0117: 'DateTime' does not contain a definition for 'NowAndThen'
```
-Line 2, column 6 in `page.razor` is where the text `@DateTime.NowAndThen` begins. That's noted by `(2, 6)` in the directive. That span of `@DateTime.NowAndThen` ends at line 2, column 27. That's noted by the `(2, 27)` in the directive. The text for `DateTime.NowAndThen` begins in column 15 of `page.g.cs`. That's noted by the `15` in the directive. Putting all the arguments together, and the compiler reports the error in its location in `page.razor`. The developer can navigate directly to the error in their source code, not the generated source.
+Line 2, column 6 in `page.razor` is where the text `@DateTime.NowAndThen` begins, noted by `(2, 6)` in the directive. That span of `@DateTime.NowAndThen` ends at line 2, column 27, noted by the `(2, 27)` in the directive. The text for `DateTime.NowAndThen` begins in column 15 of `page.g.cs`, noted by the `15` in the directive. The compiler reports the error in its location in `page.razor`. The developer can navigate directly to the error in their source code, not the generated source.
To see more examples of this format, see the [feature specification](~/_csharplang/proposals/csharp-10.0/enhanced-line-directives.md#examples) in the section on examples.
## Pragmas
-`#pragma` gives the compiler special instructions for the compilation of the file in which it appears. The instructions must be supported by the compiler. In other words, you can't use `#pragma` to create custom preprocessing instructions.
+`#pragma` gives the compiler special instructions for the compilation of the file in which it appears. The compiler must support the pragmas you use. In other words, you can't use `#pragma` to create custom preprocessing instructions.
- [`#pragma warning`](#pragma-warning): Enable or disable warnings.
- [`#pragma checksum`](#pragma-checksum): Generate a checksum.
@@ -336,14 +334,14 @@ Where `pragma-name` is the name of a recognized pragma and `pragma-arguments` is
### #pragma warning
-`#pragma warning` can enable or disable certain warnings.
+`#pragma warning` can enable or disable certain warnings. The `#pragma warning disable format` and `#pragma warning enable format` control how Visual Studio formats code blocks.
```csharp
#pragma warning disable warning-list
#pragma warning restore warning-list
```
-Where `warning-list` is a comma-separated list of warning numbers. The "CS" prefix is optional. When no warning numbers are specified, `disable` disables all warnings and `restore` enables all warnings.
+Where `warning-list` is a comma-separated list of warning numbers, such as `414, CS3021`. The "CS" prefix is optional. When no warning numbers are specified, `disable` disables all warnings and `restore` enables all warnings.
> [!NOTE]
> To find warning numbers in Visual Studio, build your project and then look for the warning numbers in the **Output** window.
@@ -374,6 +372,15 @@ public class D
}
```
+Another form of the `warning` pragma disables or restores Visual Studio formatting commands in blocks of code:
+
+```csharp
+#pragma warning disable format
+#pragma warning restore format
+```
+
+Visual Studio format commands don't modify text in blocks of code where `disable format` is in effect. Format commands, such as Ctrl+K , Ctrl+D , don't modify those regions of code. This pragma gives you fine control over the visual presentation of your code.
+
### #pragma checksum
Generates checksums for source files to aid with debugging ASP.NET pages.
diff --git a/docs/csharp/linq/get-started/query-expression-basics.md b/docs/csharp/linq/get-started/query-expression-basics.md
index bc32690523a9a..e0cc368e9ae8d 100644
--- a/docs/csharp/linq/get-started/query-expression-basics.md
+++ b/docs/csharp/linq/get-started/query-expression-basics.md
@@ -1,7 +1,7 @@
---
title: Query expression basics (LINQ)
description: Introduces concepts related to query expressions
-ms.date: 03/06/2024
+ms.date: 01/16/2025
---
# Query expression basics
@@ -52,7 +52,7 @@ A query expression must begin with a [from](../../language-reference/keywords/fr
In LINQ, a query variable is any variable that stores a *query* instead of the *results* of a query. More specifically, a query variable is always an enumerable type that produces a sequence of elements when iterated over in a `foreach` statement or a direct call to its method.
> [!NOTE]
-> Examples in this article uses the following data source and sample data.
+> Examples in this article use the following data source and sample data.
:::code language="csharp" source="./snippets/SnippetApp/DataSources.cs" id="basics_datasource":::
@@ -62,7 +62,7 @@ The following code example shows a simple query expression with one data source,
:::code language="csharp" source="./snippets/SnippetApp/Basics.cs" id="basics5":::
-In the previous example, `scoreQuery` is a *query variable,* which is sometimes referred to as just a *query*. The query variable stores no actual result data, which is produced in the `foreach` loop. And when the `foreach` statement executes, the query results aren't returned through the query variable `scoreQuery`. Rather, they're returned through the iteration variable `testScore`. The `scoreQuery` variable can be iterated in a second `foreach` loop. It produces the same results as long as neither it nor the data source has been modified.
+In the previous example, `scoreQuery` is a *query variable,* which is sometimes referred to as just a *query*. The query variable stores no actual result data, which is produced in the `foreach` loop. And when the `foreach` statement executes, the query results aren't returned through the query variable `scoreQuery`. Rather, they're returned through the iteration variable `testScore`. The `scoreQuery` variable can be iterated in a second `foreach` loop. It produces the same results as long as neither it nor the data source was modified.
A query variable might store a query that is expressed in query syntax or method syntax, or a combination of the two. In the following examples, both `queryMajorCities` and `queryMajorCities2` are query variables:
@@ -100,7 +100,7 @@ For more information, see [from clause](../../language-reference/keywords/from-c
A query expression must end with either a `group` clause or a `select` clause.
-#### group clause
+#### The group clause
Use the `group` clause to produce a sequence of groups organized by a key that you specify. The key can be any data type. For example, the following query creates a sequence of groups that contains one or more `Country` objects and whose key is a `char` type with value being the first letter of countries' names.
@@ -134,7 +134,7 @@ For more information, see [into](../../language-reference/keywords/into.md).
Between the starting `from` clause, and the ending `select` or `group` clause, all other clauses (`where`, `join`, `orderby`, `from`, `let`) are optional. Any of the optional clauses might be used zero times or multiple times in a query body.
-#### where clause
+#### The where clause
Use the `where` clause to filter out elements from the source data based on one or more predicate expressions. The `where` clause in the following example has one predicate with two conditions.
@@ -142,7 +142,7 @@ Use the `where` clause to filter out elements from the source data based on one
For more information, see [where clause](../../language-reference/keywords/where-clause.md).
-#### orderby clause
+#### The orderby clause
Use the `orderby` clause to sort the results in either ascending or descending order. You can also specify secondary sort orders. The following example performs a primary sort on the `country` objects by using the `Area` property. It then performs a secondary sort by using the `Population` property.
@@ -150,7 +150,7 @@ Use the `orderby` clause to sort the results in either ascending or descending o
The `ascending` keyword is optional; it's the default sort order if no order is specified. For more information, see [orderby clause](../../language-reference/keywords/orderby-clause.md).
-#### join clause
+#### The join clause
Use the `join` clause to associate and/or combine elements from one data source with elements from another data source based on an equality comparison between specified keys in each element. In LINQ, join operations are performed on sequences of objects whose elements are different types. After you join two sequences, you must use a `select` or `group` statement to specify which element to store in the output sequence. You can also use an anonymous type to combine properties from each set of associated elements into a new type for the output sequence. The following example associates `prod` objects whose `Category` property matches one of the categories in the `categories` string array. Products whose `Category` doesn't match any string in `categories` are filtered out. The `select` statement projects a new type whose properties are taken from both `cat` and `prod`.
@@ -158,7 +158,7 @@ Use the `join` clause to associate and/or combine elements from one data source
You can also perform a group join by storing the results of the `join` operation into a temporary variable by using the [into](../../language-reference/keywords/into.md) keyword. For more information, see [join clause](../../language-reference/keywords/join-clause.md).
-#### let clause
+#### The let clause
Use the `let` clause to store the result of an expression, such as a method call, in a new range variable. In the following example, the range variable `firstName` stores the first element of the array of strings returned by `Split`.
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/Basics.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/Basics.cs
index 9ce7f6c4ef4c3..624b74483c9b0 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/Basics.cs
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/Basics.cs
@@ -3,7 +3,13 @@
public static class Basics
{
- static readonly int[] scores = [0]; // Max is called on this, so one value is needed
+ static readonly int[] scores =
+ [
+ 0, 30, 50, 70, 80,
+ 85, 94, 87, 96, 88,
+ 59, 90, 91, 85, 60,
+ 49, 100
+ ];
//
static readonly City[] cities = [
@@ -50,6 +56,10 @@ where score > 80
orderby score descending
select score;
//
+ foreach(var score in highScoresQuery)
+ {
+ Console.WriteLine(score);
+ }
}
public static void Basics2()
@@ -61,6 +71,10 @@ where score > 80
orderby score descending
select $"The score is {score}";
//
+ foreach (var score in highScoresQuery2)
+ {
+ Console.WriteLine(score);
+ }
}
public static void Basics3()
@@ -72,6 +86,7 @@ where score > 80
select score
).Count();
//
+ Console.WriteLine($"highest score: {highScoreCount}");
}
public static void Basics4()
@@ -84,6 +99,7 @@ where score > 80
var scoreCount = highScoresQuery3.Count();
//
+ Console.WriteLine($"highest score: {scoreCount}");
}
public static void Basics5()
@@ -122,7 +138,7 @@ public static void Basics6()
//Query syntax
IEnumerable queryMajorCities =
from city in cities
- where city.Population > 100000
+ where city.Population > 30_000_000
select city;
// Execute the query to produce the results
@@ -132,12 +148,19 @@ where city.Population > 100000
}
// Output:
- // City { Population = 120000 }
- // City { Population = 112000 }
- // City { Population = 150340 }
-
+ // City { Name = Tokyo, Population = 37833000 }
+ // City { Name = Delhi, Population = 30290000 }
+
// Method-based syntax
- IEnumerable queryMajorCities2 = cities.Where(c => c.Population > 100000);
+ IEnumerable queryMajorCities2 = cities.Where(c => c.Population > 30_000_000);
+ // Execute the query to produce the results
+ foreach (City city in queryMajorCities2)
+ {
+ Console.WriteLine(city);
+ }
+ // Output:
+ // City { Name = Tokyo, Population = 37833000 }
+ // City { Name = Delhi, Population = 30290000 }
//
}
@@ -158,6 +181,8 @@ from score in scores
// the following returns the same result
highScore = scores.Max();
//
+ Console.WriteLine($"highest score: {highestScore}");
+ Console.WriteLine($"high Score: {highScore}");
}
public static void Basics7a()
@@ -178,6 +203,14 @@ where city.Population > 10000
select city;
var largeCitiesList2 = largeCitiesQuery.ToList();
//
+ foreach(var item in largeCitiesList)
+ {
+ Console.WriteLine(item.Name + ":" + item.Population);
+ }
+ foreach (var item in largeCitiesList2)
+ {
+ Console.WriteLine(item.Name + ":" + item.Population);
+ }
}
public static void Basics8()
@@ -188,6 +221,10 @@ from city in cities
where city.Population > 100000
select city;
//
+ foreach (var city in queryCities)
+ {
+ Console.WriteLine(city.Name + ":" + city.Population);
+ }
}
public static void Basics9()
@@ -195,9 +232,13 @@ public static void Basics9()
//
IEnumerable countryAreaQuery =
from country in countries
- where country.Area > 500000 //sq km
+ where country.Area > 20 //sq km
select country;
//
+ foreach (var country in countryAreaQuery)
+ {
+ Console.WriteLine(country.Name + ":" + country.Area);
+ }
}
public static void Basics10()
@@ -209,6 +250,10 @@ from city in country.Cities
where city.Population > 10000
select city;
//
+ foreach (var city in cityQuery)
+ {
+ Console.WriteLine(city.Name + ":" + city.Population);
+ }
}
public static void Basics11()
@@ -218,6 +263,14 @@ public static void Basics11()
from country in countries
group country by country.Name[0];
//
+ foreach (var group in queryCountryGroups)
+ {
+ Console.WriteLine(group.Key);
+ foreach (var country in group)
+ {
+ Console.WriteLine(country.Name);
+ }
+ }
}
public static void Basics12()
@@ -228,6 +281,10 @@ from country in countries
orderby country.Area
select country;
//
+ foreach (var country in sortedQuery)
+ {
+ Console.WriteLine(country.Name + ":" + country.Area);
+ }
}
public static void Basics13()
@@ -241,6 +298,10 @@ from country in countries
Pop = country.Population
};
//
+ foreach (var item in queryNameAndPop)
+ {
+ Console.WriteLine(item.Name + ":" + item.Pop);
+ }
}
public static void Basics14()
@@ -249,7 +310,7 @@ public static void Basics14()
// percentileQuery is an IEnumerable>
var percentileQuery =
from country in countries
- let percentile = (int)country.Population / 10_000_000
+ let percentile = (int)country.Population / 1_000
group country by percentile into countryGroup
where countryGroup.Key >= 20
orderby countryGroup.Key
@@ -272,9 +333,13 @@ public static void Basics15()
//
IEnumerable queryCityPop =
from city in cities
- where city.Population is < 200000 and > 100000
+ where city.Population is < 15_000_000 and > 10_000_000
select city;
//
+ foreach (var city in queryCityPop)
+ {
+ Console.WriteLine(city.Name + ":" + city.Population);
+ }
}
public static void Basics16()
@@ -285,12 +350,25 @@ from country in countries
orderby country.Area, country.Population descending
select country;
//
+ foreach (var country in querySortedCountries)
+ {
+ Console.WriteLine(country.Name + ":" + country.Area + ":" + country.Population);
+ }
}
public static void Basics17()
{
- string[] categories = [];
- Product[] products = [];
+ string[] categories = ["brass", "winds", "percussion"];
+ Product[] products =
+ [
+ new Product("Trumpet", "brass"),
+ new Product("Trombone", "brass"),
+ new Product("French Horn", "brass"),
+ new Product("Clarinet", "winds"),
+ new Product("Flute", "winds"),
+ new Product("Cymbal", "percussion"),
+ new Product("Drum", "percussion")
+ ];
//
var categoryQuery =
@@ -302,6 +380,10 @@ join prod in products on cat equals prod.Category
Name = prod.Name
};
//
+ foreach (var item in categoryQuery)
+ {
+ Console.WriteLine(item.Category + ":" + item.Name);
+ }
}
public static void Basics18()
@@ -339,5 +421,9 @@ select student2.ExamScores.Average()
).Max()
};
//
+ foreach (var item in queryGroupMax)
+ {
+ Console.WriteLine(item.Level + ":" + item.HighestScore);
+ }
}
}
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/Exceptions.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/Exceptions.cs
index b1f842bf60fe2..c4190e027dbda 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/Exceptions.cs
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/Exceptions.cs
@@ -23,9 +23,8 @@ public static void Exceptions1()
if (dataSource is not null)
{
// If we get here, it is safe to proceed.
- var query =
- from i in dataSource
- select i * i;
+ var query = from i in dataSource
+ select i * i;
foreach (var i in query)
{
@@ -42,16 +41,15 @@ public static void Exceptions2()
string SomeMethodThatMightThrow(string s) =>
s[4] == 'C' ?
throw new InvalidOperationException() :
- @"C:\newFolder\" + s;
+ $"""C:\newFolder\{s}""";
// Data source.
string[] files = ["fileA.txt", "fileB.txt", "fileC.txt"];
// Demonstration query that throws.
- var exceptionDemoQuery =
- from file in files
- let n = SomeMethodThatMightThrow(file)
- select n;
+ var exceptionDemoQuery = from file in files
+ let n = SomeMethodThatMightThrow(file)
+ select n;
try
{
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/LinqGetStarted.csproj b/docs/csharp/linq/get-started/snippets/SnippetApp/LinqGetStarted.csproj
index 13b6b87ef23cd..8522f376c0a40 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/LinqGetStarted.csproj
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/LinqGetStarted.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net9.0
Linq.GetStarted
enable
enable
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/NullValues.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/NullValues.cs
index aaf4fe4733bb6..9bd2cb5c33f29 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/NullValues.cs
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/NullValues.cs
@@ -1,25 +1,49 @@
namespace LinqSamples;
+//
record Product(string Name, int CategoryID);
record Category(string Name, int ID);
+//
+
public static class NullValues
{
- static readonly Category[] categories = [];
- static readonly Product[] products = [];
+ //
+ static Category?[] categories =
+ [
+ new ("brass", 1),
+ null,
+ new ("winds", 2),
+ default,
+ new ("percussion", 3)
+ ];
+
+ static Product?[] products =
+ [
+ new Product("Trumpet", 1),
+ new Product("Trombone", 1),
+ new Product("French Horn", 1),
+ null,
+ new Product("Clarinet", 2),
+ new Product("Flute", 2),
+ null,
+ new Product("Cymbal", 3),
+ new Product("Drum", 3)
+ ];
+ //
+
public static void NullValues1()
{
//
- var query1 =
- from c in categories
- where c != null
- join p in products on c.ID equals p?.CategoryID
- select new
- {
- Category = c.Name,
- Name = p.Name
- };
+ var query1 = from c in categories
+ where c != null
+ join p in products on c.ID equals p?.CategoryID
+ select new
+ {
+ Category = c.Name,
+ Name = p.Name
+ };
//
}
}
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/Program.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/Program.cs
index b38cb84a5047e..37eb3d63eab87 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/Program.cs
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/Program.cs
@@ -2,6 +2,7 @@
WriteSeparator(nameof(PartsOfAQuery));
PartsOfAQuery();
+Console.WriteLine();
WriteSeparator(nameof(Linq.GetStarted.Basics.Basics1));
Linq.GetStarted.Basics.Basics1();
@@ -41,6 +42,7 @@
Linq.GetStarted.Basics.Basics17();
WriteSeparator(nameof(Linq.GetStarted.Basics.Basics18));
Linq.GetStarted.Basics.Basics18();
+Console.WriteLine();
WriteSeparator(nameof(Linq.GetStarted.Basics.Basics19));
Linq.GetStarted.Basics.Basics19();
@@ -103,10 +105,9 @@ static void PartsOfAQuery()
// 2. Query creation.
// numQuery is an IEnumerable
- var numQuery =
- from num in numbers
- where (num % 2) == 0
- select num;
+ var numQuery = from num in numbers
+ where (num % 2) == 0
+ select num;
// 3. Query execution.
foreach (int num in numQuery)
@@ -123,26 +124,23 @@ from num in numbers
//
//
- var evenNumQuery =
- from num in numbers
- where (num % 2) == 0
- select num;
+ var evenNumQuery = from num in numbers
+ where (num % 2) == 0
+ select num;
int evenNumCount = evenNumQuery.Count();
//
//
- List numQuery2 =
- (from num in numbers
- where (num % 2) == 0
- select num).ToList();
+ List numQuery2 = (from num in numbers
+ where (num % 2) == 0
+ select num).ToList();
// or like this:
// numQuery3 is still an int[]
- var numQuery3 =
- (from num in numbers
- where (num % 2) == 0
- select num).ToArray();
+ var numQuery3 = (from num in numbers
+ where (num % 2) == 0
+ select num).ToArray();
//
}
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/ReturnQueryFromMethod.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/ReturnQueryFromMethod.cs
index bf6f06adc56ac..8476640e347f1 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/ReturnQueryFromMethod.cs
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/ReturnQueryFromMethod.cs
@@ -11,12 +11,11 @@ where i > 4
select i.ToString();
void QueryMethod2(int[] ints, out IEnumerable returnQ) =>
- returnQ =
- from i in ints
- where i < 4
- select i.ToString();
+ returnQ = from i in ints
+ where i < 4
+ select i.ToString();
- int[] nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+ int[] nums = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
var myQuery1 = QueryMethod1(nums);
//
@@ -49,10 +48,9 @@ where i < 4
//
//
- myQuery1 =
- from item in myQuery1
- orderby item descending
- select item;
+ myQuery1 = from item in myQuery1
+ orderby item descending
+ select item;
// Execute the modified query.
Console.WriteLine("\nResults of executing modified myQuery1:");
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/RuntimeFiltering.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/RuntimeFiltering.cs
index 87f5549f57338..6b0691023f239 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/RuntimeFiltering.cs
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/RuntimeFiltering.cs
@@ -7,16 +7,15 @@ public static class RuntimeFiltering
public static void RuntimeFiltering1()
{
//
- int[] ids = [111, 114, 112];
+ int[] ids = [ 111, 114, 112 ];
- var queryNames =
- from student in students
- where ids.Contains(student.ID)
- select new
- {
- student.LastName,
- student.ID
- };
+ var queryNames = from student in students
+ where ids.Contains(student.ID)
+ select new
+ {
+ student.LastName,
+ student.ID
+ };
foreach (var name in queryNames)
{
@@ -30,7 +29,7 @@ where ids.Contains(student.ID)
*/
// Change the ids.
- ids = [122, 117, 120, 115];
+ ids = [ 122, 117, 120, 115 ];
// The query will now return different results
foreach (var name in queryNames)
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/StoreResultsOfQueryInMemory.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/StoreResultsOfQueryInMemory.cs
index 42c1f6c78b5bd..cb79aa568a0ed 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/StoreResultsOfQueryInMemory.cs
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/StoreResultsOfQueryInMemory.cs
@@ -5,12 +5,11 @@ public static class StoreResultsOfQueryInMemory
public static void StoreResultsOfQueryInMemory1()
{
//
- List numbers = [1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
+ List numbers = [ 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 ];
- IEnumerable queryFactorsOfFour =
- from num in numbers
- where num % 4 == 0
- select num;
+ IEnumerable queryFactorsOfFour = from num in numbers
+ where num % 4 == 0
+ select num;
// Store the results in a new variable
// without executing a foreach loop.
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/TypeRelationships.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/TypeRelationships.cs
index d3421ee7b5390..cca43c6e0c51d 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/TypeRelationships.cs
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/TypeRelationships.cs
@@ -9,15 +9,14 @@ class Customer
public string FirstName { get; set; }
public string Phone {get; set;}
}
- static List customers = new List();
+ static List customers = new ();
public static void ExplicitType()
{
//
- IEnumerable customerQuery =
- from cust in customers
- where cust.City == "London"
- select cust;
+ IEnumerable customerQuery = from cust in customers
+ where cust.City == "London"
+ select cust;
foreach (Customer customer in customerQuery)
{
@@ -29,10 +28,9 @@ from cust in customers
public static void ImplicitType()
{
//
- var customerQuery2 =
- from cust in customers
- where cust.City == "London"
- select cust;
+ var customerQuery2 = from cust in customers
+ where cust.City == "London"
+ select cust;
foreach(var customer in customerQuery2)
{
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/WriteLinqQueries.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/WriteLinqQueries.cs
index f17b7b02ab110..b21e2aa8d378c 100644
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/WriteLinqQueries.cs
+++ b/docs/csharp/linq/get-started/snippets/SnippetApp/WriteLinqQueries.cs
@@ -2,9 +2,9 @@
public class WriteLinqQueries
{
- static readonly List numbers = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0];
- static readonly List numbers1 = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0];
- static readonly List numbers2 = [15, 14, 11, 13, 19, 18, 16, 17, 12, 10];
+ static readonly List numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ];
+ static readonly List numbers1 = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ];
+ static readonly List numbers2 = [ 15, 14, 11, 13, 19, 18, 16, 17, 12, 10 ];
public static void MethodSyntax()
{
@@ -19,7 +19,9 @@ orderby num
select num;
//Method syntax:
- IEnumerable numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
+ IEnumerable numQuery2 = numbers
+ .Where(num => num % 2 == 0)
+ .OrderBy(n => n);
foreach (int i in numQuery1)
{
@@ -36,7 +38,7 @@ orderby num
public static void WriteLinqQueries1()
{
//
- List numbers = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0];
+ List numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ];
// The query variables can also be implicitly typed by using var
@@ -64,8 +66,8 @@ from item in groupingQuery
public static void WriteLinqQueries2()
{
//
- List numbers1 = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0];
- List numbers2 = [15, 14, 11, 13, 19, 18, 16, 17, 12, 10];
+ List numbers1 = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ];
+ List numbers2 = [ 15, 14, 11, 13, 19, 18, 16, 17, 12, 10 ];
// Query #4.
double average = numbers1.Average();
diff --git a/docs/csharp/linq/get-started/snippets/SnippetApp/how-to-handle-null-values-in-query-expressions_2.cs b/docs/csharp/linq/get-started/snippets/SnippetApp/how-to-handle-null-values-in-query-expressions_2.cs
deleted file mode 100644
index 5f282702bb03e..0000000000000
--- a/docs/csharp/linq/get-started/snippets/SnippetApp/how-to-handle-null-values-in-query-expressions_2.cs
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/csharp/linq/get-started/write-linq-queries.md b/docs/csharp/linq/get-started/write-linq-queries.md
index 2ad2a5eac7e16..6e64fab2fd58d 100644
--- a/docs/csharp/linq/get-started/write-linq-queries.md
+++ b/docs/csharp/linq/get-started/write-linq-queries.md
@@ -1,11 +1,11 @@
---
title: Write LINQ queries
description: Learn how to write LINQ queries in C#.
-ms.date: 04/19/2024
+ms.date: 01/16/2025
---
# Write C# LINQ queries to query data
-Most queries in the introductory Language Integrated Query (LINQ) documentation are written by using the LINQ declarative query syntax. However, the query syntax must be translated into method calls for the .NET common language runtime (CLR) when the code is compiled. These method calls invoke the standard query operators, which have names such as `Where`, `Select`, `GroupBy`, `Join`, `Max`, and `Average`. You can call them directly by using method syntax instead of query syntax.
+Most queries in the introductory Language Integrated Query (LINQ) documentation are written by using the LINQ declarative query syntax. The C# compiler translates query syntax into method calls. These method calls implement the standard query operators, and have names such as `Where`, `Select`, `GroupBy`, `Join`, `Max`, and `Average`. You can call them directly by using method syntax instead of query syntax.
Query syntax and method syntax are semantically identical, but query syntax is often simpler and easier to read. Some queries must be expressed as method calls. For example, you must use a method call to express a query that retrieves the number of elements that match a specified condition. You also must use a method call for a query that retrieves the element that has the maximum value in a source sequence. The reference documentation for the standard query operators in the namespace generally uses method syntax. You should become familiar with how to use method syntax in queries and in query expressions themselves.
@@ -15,30 +15,28 @@ The following example shows a simple *query expression* and the semantically equ
:::code language="csharp" source="./snippets/SnippetApp/WriteLinqQueries.cs" id="MethodSyntax":::
-The output from the two examples is identical. You can see that the type of the query variable is the same in both forms: .
+The output from the two examples is identical. The type of the query variable is the same in both forms: .
-To understand the method-based query, let's examine it more closely. On the right side of the expression, notice that the `where` clause is now expressed as an instance method on the `numbers` object, which has a type of `IEnumerable`. If you're familiar with the generic interface, you know that it doesn't have a `Where` method. However, if you invoke the IntelliSense completion list in the Visual Studio IDE, you see not only a `Where` method, but many other methods such as `Select`, `SelectMany`, `Join`, and `Orderby`. These methods implement the standard query operators.
+On the right side of the expression, notice that the `where` clause is now expressed as an instance method on the `numbers` object, which has a type of `IEnumerable`. If you're familiar with the generic interface, you know that it doesn't have a `Where` method. However, if you invoke the IntelliSense completion list in the Visual Studio IDE, you see not only a `Where` method, but many other methods such as `Select`, `SelectMany`, `Join`, and `Orderby`. These methods implement the standard query operators.

-Although it looks as if includes more methods, it doesn't. The standard query operators are implemented as *extension methods*. Extensions methods "extend" an existing type; they can be called as if they were instance methods on the type. The standard query operators extend and that is why you can write `numbers.Where(...)`.
-
-To use extension methods, you bring them into scope with `using` directives. From your application's point of view, an extension method and a regular instance method are the same.
+Although it looks as if includes more methods, it doesn't. The standard query operators are implemented as *extension methods*. Extensions methods "extend" an existing type; they can be called as if they were instance methods on the type. The standard query operators extend and that is why you can write `numbers.Where(...)`. You bring extensions into scope with `using` directives before calling them.
For more information about extension methods, see [Extension Methods](../../programming-guide/classes-and-structs/extension-methods.md). For more information about standard query operators, see [Standard Query Operators Overview (C#)](../standard-query-operators/index.md). Some LINQ providers, such as [Entity Framework](/ef/core/) and LINQ to XML, implement their own standard query operators and extension methods for other types besides .
## Lambda expressions
-In the previous example, notice that the conditional expression (`num % 2 == 0`) is passed as an in-line argument to the method: `Where(num => num % 2 == 0).` This inline expression is a [lambda expression](../../language-reference/operators/lambda-expressions.md). It's a convenient way to write code that would otherwise have to be written in more cumbersome form. The `num` on the left of the operator is the input variable, which corresponds to `num` in the query expression. The compiler can infer the type of `num` because it knows that `numbers` is a generic type. The body of the lambda is just the same as the expression in query syntax or in any other C# expression or statement. It can include method calls and other complex logic. The return value is just the expression result. Certain queries can only be expressed in method syntax and some of those require lambda expressions. Lambda expressions are a powerful and flexible tool in your LINQ toolbox.
+In the preceding example, the conditional expression (`num % 2 == 0`) is passed as an in-line argument to the method: `Where(num => num % 2 == 0).` This inline expression is a [lambda expression](../../language-reference/operators/lambda-expressions.md). It's a convenient way to write code that would otherwise have to be written in more cumbersome form. The `num` on the left of the operator is the input variable, which corresponds to `num` in the query expression. The compiler can infer the type of `num` because it knows that `numbers` is a generic type. The body of the lambda is the same as the expression in query syntax or in any other C# expression or statement. It can include method calls and other complex logic. The return value is the expression result. Certain queries can only be expressed in method syntax and some of those queries require lambda expressions. Lambda expressions are a powerful and flexible tool in your LINQ toolbox.
## Composability of queries
-In the previous code example, the method is invoked by using the dot operator on the call to `Where`. `Where` produces a filtered sequence, and then `Orderby` sorts the sequence produced by `Where`. Because queries return an `IEnumerable`, you compose them in method syntax by chaining the method calls together. The compiler does this composition when you write queries using query syntax. Because a query variable doesn't store the results of the query, you can modify it or use it as the basis for a new query at any time, even after you execute it.
+In the preceding code example, the method is invoked by using the dot operator on the call to `Where`. `Where` produces a filtered sequence, and then `Orderby` sorts the sequence produced by `Where`. Because queries return an `IEnumerable`, you compose them in method syntax by chaining the method calls together. The compiler does this composition when you write queries using query syntax. Because a query variable doesn't store the results of the query, you can modify it or use it as the basis for a new query at any time, even after you execute it.
-The following examples demonstrate some simple LINQ queries by using each approach listed previously.
+The following examples demonstrate some basic LINQ queries by using each approach listed previously.
> [!NOTE]
-> These queries operate on simple in-memory collections; however, the basic syntax is identical to that used in LINQ to Entities and LINQ to XML.
+> These queries operate on in-memory collections; however, the syntax is identical to that used in LINQ to Entities and LINQ to XML.
## Example - Query syntax
@@ -54,7 +52,7 @@ In each previous example, the queries don't actually execute until you iterate o
## Example - Method syntax
-Some query operations must be expressed as a method call. The most common such methods are those methods that return singleton numeric values, such as , , , , and so on. These methods must always be called last in any query because they return a single value and can't serve as the source for an extra query operation. The following example shows a method call in a query expression:
+Some query operations must be expressed as a method call. The most common such methods are those methods that return singleton numeric values, such as , , , , and so on. These methods must always be called last in any query because they return a single value and can't serve as the source for an additional query operation. The following example shows a method call in a query expression:
:::code language="csharp" source="./snippets/SnippetApp/WriteLinqQueries.cs" id="write_linq_queries_2":::
@@ -70,7 +68,7 @@ Each of the previous queries can be written by using implicit typing with [`var`
## Example - Mixed query and method syntax
-This example shows how to use method syntax on the results of a query clause. Just enclose the query expression in parentheses, and then apply the dot operator and call the method. In the following example, query #7 returns a count of the numbers whose value is between 3 and 7. In general, however, it's better to use a second variable to store the result of the method call. In this manner, the query is less likely to be confused with the results of the query.
+This example shows how to use method syntax on the results of a query clause. Just enclose the query expression in parentheses, and then apply the dot operator and call the method. In the following example, query #7 returns a count of the numbers whose value is between 3 and 7.
:::code language="csharp" source="./snippets/SnippetApp/WriteLinqQueries.cs" id="write_linq_queries_5":::
@@ -96,6 +94,13 @@ In some cases, you don't know until run time how many predicates you have to app
:::code language="csharp" source="./snippets/SnippetApp/RuntimeFiltering.cs" id="runtime_filtering_1":::
+> [!NOTE]
+> This example uses the following data source and data:
+
+:::code language="csharp" source="./snippets/SnippetApp/DataSources.cs" id="basics_datasource":::
+
+:::code language="csharp" source="./snippets/SnippetApp/Basics.cs" id="SourceData":::
+
You can use control flow statements, such as `if... else` or `switch`, to select among predetermined alternative queries. In the following example, `studentQuery` uses a different `where` clause if the run-time value of `oddYear` is `true` or `false`.
:::code language="csharp" source="./snippets/SnippetApp/RuntimeFiltering.cs" id="runtime_filtering_2":::
@@ -104,6 +109,12 @@ You can use control flow statements, such as `if... else` or `switch`, to select
This example shows how to handle possible null values in source collections. An object collection such as an can contain elements whose value is [null](../../language-reference/keywords/null.md). If a source collection is `null` or contains an element whose value is `null`, and your query doesn't handle `null` values, a is thrown when you execute the query.
+The following example uses these types and static data arrays:
+
+:::code language="csharp" source="./snippets/SnippetApp/NullValues.cs" id="dataSourceTypes":::
+
+:::code language="csharp" source="./snippets/SnippetApp/NullValues.cs" id="source":::
+
You can code defensively to avoid a null reference exception as shown in the following example:
:::code language="csharp" source="./snippets/SnippetApp/NullValues.cs" id="null_values_1":::
@@ -124,7 +135,7 @@ In each of the examples, the `equals` query keyword is used. You can also use [p
## Handle exceptions in query expressions
-It's possible to call any method in the context of a query expression. Don't call any method in a query expression that can create a side effect such as modifying the contents of the data source or throwing an exception. This example shows how to avoid raising exceptions when you call methods in a query expression without violating the general .NET guidelines on exception handling. Those guidelines state that it's acceptable to catch a specific exception when you understand why it's thrown in a given context. For more information, see [Best Practices for Exceptions](../../../standard/exceptions/best-practices-for-exceptions.md).
+It's possible to call any method in the context of a query expression. Don't call any method in a query expression that can create a side effect such as modifying the contents of the data source or throwing an exception. This example shows how to avoid raising exceptions when you call methods in a query expression without violating the general .NET guidelines on exception handling. Those guidelines state that it's acceptable to catch a specific exception when you understand why it was thrown in a given context. For more information, see [Best Practices for Exceptions](../../../standard/exceptions/best-practices-for-exceptions.md).
The final example shows how to handle those cases when you must throw an exception during execution of a query.
@@ -144,7 +155,6 @@ Remember to catch whatever exception you expect to raise and/or do any necessary
## See also
-- [Walkthrough: Writing Queries in C#](walkthrough-writing-queries-linq.md)
- [where clause](../../language-reference/keywords/where-clause.md)
- [Querying based on runtime state](../../advanced-topics/expression-trees/debugview-syntax.md)
-
diff --git a/docs/csharp/programming-guide/classes-and-structs/constructors.md b/docs/csharp/programming-guide/classes-and-structs/constructors.md
index fa089538c295f..88c8232459985 100644
--- a/docs/csharp/programming-guide/classes-and-structs/constructors.md
+++ b/docs/csharp/programming-guide/classes-and-structs/constructors.md
@@ -1,7 +1,7 @@
---
title: "Constructors"
description: A constructor in C# is called when a class or struct is created. Use constructors to set defaults, limit instantiation, and write flexible, easy-to-read code.
-ms.date: 04/06/2023
+ms.date: 01/15/2025
helpviewer_keywords:
- "constructors [C#]"
- "classes [C#], constructors"
@@ -9,34 +9,38 @@ helpviewer_keywords:
---
# Constructors (C# programming guide)
-Whenever an instance of a [class](../../language-reference/keywords/class.md) or a [struct](../../language-reference/builtin-types/struct.md) is created, its constructor is called. A class or struct may have multiple constructors that take different arguments. Constructors enable the programmer to set default values, limit instantiation, and write code that is flexible and easy to read. For more information and examples, see [Instance constructors](instance-constructors.md) and [Using constructors](using-constructors.md).
+A *constructor* is a method called by the runtime when an instance of a [class](../../language-reference/keywords/class.md) or a [struct](../../language-reference/builtin-types/struct.md) is created. A class or struct can have multiple constructors that take different arguments. Constructors enable you to ensure that instances of the type are valid when created. For more information and examples, see [Instance constructors](instance-constructors.md) and [Using constructors](using-constructors.md).
-There are several actions that are part of initializing a new instance. Those actions take place in the following order:
+There are several actions that are part of initializing a new instance. The following actions take place in the following order:
-1. *Instance fields are set to 0*. This is typically done by the runtime.
+1. *Instance fields are set to 0*. This initialization is typically done by the runtime.
1. *Field initializers run*. The field initializers in the most derived type run.
1. *Base type field initializers run*. Field initializers starting with the direct base through each base type to .
1. *Base instance constructors run*. Any instance constructors, starting with through each base class to the direct base class.
1. *The instance constructor runs*. The instance constructor for the type runs.
-1. *Object initializers run*. If the expression includes any object initializers, those run after the instance constructor runs. Object initializers run in the textual order.
+1. *Object initializers run*. If the expression includes any object initializers, they run after the instance constructor runs. Object initializers run in the textual order.
-The preceding actions take place when a new instance is initialized. If a new instance of a `struct` is set to its `default` value, all instance fields are set to 0.
+The preceding actions take place when an instance is created using the [`new` operator](../../language-reference//operators/new-operator.md). If a new instance of a `struct` is set to its `default` value, all instance fields are set to 0. Elements of an array are set to their default value of 0 or `null` when an array is created.
-If the [static constructor](static-constructors.md) hasn't run, the static constructor runs before any of the instance constructor actions take place.
+The [static constructor](static-constructors.md), if any, runs before any of the instance constructor actions take place for any instance of the type. The static constructor runs at most once.
## Constructor syntax
-A constructor is a method whose name is the same as the name of its type. Its method signature includes only an optional [access modifier](./access-modifiers.md), the method name and its parameter list; it does not include a return type. The following example shows the constructor for a class named `Person`.
+A constructor is a method with the same name as its type. Its method signature can include an optional [access modifier](./access-modifiers.md), the method name, and its parameter list; it doesn't include a return type. The following example shows the constructor for a class named `Person`.
:::code source="./snippets/constructors/Program.cs" id="InstanceCtor":::
-If a constructor can be implemented as a single statement, you can use an [expression body definition](../statements-expressions-operators/expression-bodied-members.md). The following example defines a `Location` class whose constructor has a single string parameter named *name*. The expression body definition assigns the argument to the `locationName` field.
+If a constructor can be implemented as a single statement, you can use an [expression body member](../statements-expressions-operators/expression-bodied-members.md). The following example defines a `Location` class whose constructor has a single string parameter named *name*. The expression body definition assigns the argument to the `locationName` field.
:::code source="./snippets/constructors/Program.cs" id="ExpressionBodiedCtor":::
+If a type requires a parameter to create an instance, you can use a *primary constructor* to indicate that one or more parameters are required to instantiate the type, as shown in the following example:
+
+:::code source="./snippets/constructors/Program.cs" id="PrimaryCtor":::
+
## Static constructors
-The previous examples have all shown instance constructors, which create a new object. A class or struct can also have a static constructor, which initializes static members of the type. Static constructors are parameterless. If you don't provide a static constructor to initialize static fields, the C# compiler initializes static fields to their default value as listed in the [Default values of C# types](../../language-reference/builtin-types/default-values.md) article.
+The previous examples show instance constructors, which initialize a new object. A class or struct can also declare a static constructor, which initializes static members of the type. Static constructors are parameterless. If you don't provide a static constructor to initialize static fields, the C# compiler initializes static fields to their default value as listed in the [Default values of C# types](../../language-reference/builtin-types/default-values.md) article.
The following example uses a static constructor to initialize a static field.
@@ -48,17 +52,8 @@ You can also define a static constructor with an expression body definition, as
For more information and examples, see [Static Constructors](./static-constructors.md).
-## In This Section
-
-- [Using constructors](./using-constructors.md)
-- [Instance constructors](./instance-constructors.md)
-- [Private constructors](./private-constructors.md)
-- [Static constructors](./static-constructors.md)
-- [How to write a copy constructor](./how-to-write-a-copy-constructor.md)
-
## See also
- [The C# type system](../../fundamentals/types/index.md)
-- [Finalizers](./finalizers.md)
-- [static](../../language-reference/keywords/static.md)
+- [`static`](../../language-reference/keywords/static.md)
- [Why Do Initializers Run In The Opposite Order As Constructors? Part One](/archive/blogs/ericlippert/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one)
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/constructors/Program.cs b/docs/csharp/programming-guide/classes-and-structs/snippets/constructors/Program.cs
index 74adb19a8cf21..9cd7ee626742a 100644
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/constructors/Program.cs
+++ b/docs/csharp/programming-guide/classes-and-structs/snippets/constructors/Program.cs
@@ -25,10 +25,7 @@ public class Adult : Person
public Adult(string lastName, string firstName) : base(lastName, firstName)
{ }
- static Adult()
- {
- minimumAge = 18;
- }
+ static Adult() => minimumAge = 18;
// Remaining implementation of Adult class.
}
@@ -63,3 +60,15 @@ public string Name
}
//
+//
+public class LabelledContainer(string label)
+{
+ public string Label { get; } = label;
+ public required T Contents
+ {
+ get;
+ init;
+ }
+}
+//
+
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/constructors/constructors.csproj b/docs/csharp/programming-guide/classes-and-structs/snippets/constructors/constructors.csproj
index 2150e3797ba5e..fd4bd08da2987 100644
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/constructors/constructors.csproj
+++ b/docs/csharp/programming-guide/classes-and-structs/snippets/constructors/constructors.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net9.0
enable
enable
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/using-constructors/Program.cs b/docs/csharp/programming-guide/classes-and-structs/snippets/using-constructors/Program.cs
index 2e63e75ddd605..03f5f3bb4919e 100644
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/using-constructors/Program.cs
+++ b/docs/csharp/programming-guide/classes-and-structs/snippets/using-constructors/Program.cs
@@ -1,20 +1,19 @@
//
public class Taxi
{
- public bool IsInitialized;
+ private string taxiTag;
- public Taxi()
- {
- IsInitialized = true;
- }
+ public Taxi(string tag) => taxiTag = tag;
+
+ public override string ToString() => $"Taxi: {taxiTag}";
}
class TestTaxi
{
static void Main()
{
- Taxi t = new Taxi();
- Console.WriteLine(t.IsInitialized);
+ Taxi t = new Taxi("Tag1345");
+ Console.WriteLine(t);
}
}
//
@@ -37,16 +36,10 @@ public class Employee
public Employee() { }
//
- public Employee(int annualSalary)
- {
- Salary = annualSalary;
- }
+ public Employee(int annualSalary) => Salary = annualSalary;
//
- public Employee(int weeklySalary, int numberOfWeeks)
- {
- Salary = weeklySalary * numberOfWeeks;
- }
+ public Employee(int weeklySalary, int numberOfWeeks) => Salary = weeklySalary * numberOfWeeks;
}
//
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/using-constructors/UsingConstructors.csproj b/docs/csharp/programming-guide/classes-and-structs/snippets/using-constructors/UsingConstructors.csproj
index cb7c096a14515..ab3409ab367b7 100644
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/using-constructors/UsingConstructors.csproj
+++ b/docs/csharp/programming-guide/classes-and-structs/snippets/using-constructors/UsingConstructors.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net9.0
enable
enable
UsingConstructors
diff --git a/docs/csharp/programming-guide/classes-and-structs/using-constructors.md b/docs/csharp/programming-guide/classes-and-structs/using-constructors.md
index e28c88aae29e5..917c90ff49b4f 100644
--- a/docs/csharp/programming-guide/classes-and-structs/using-constructors.md
+++ b/docs/csharp/programming-guide/classes-and-structs/using-constructors.md
@@ -1,19 +1,19 @@
---
title: "Using Constructors"
description: This example shows how a class is instantiated by using the new operator in C#. The simple constructor is invoked after memory is allocated for the new object.
-ms.date: 11/22/2024
+ms.date: 01/15/2025
helpviewer_keywords:
- "constructors [C#], about constructors"
---
-# Using Constructors (C# Programming Guide)
+# Use constructors (C# programming guide)
-When a [class](../../language-reference/keywords/class.md) or [struct](../../language-reference/builtin-types/struct.md) is instantiated, its constructor is called. Constructors have the same name as the class or struct, and they usually initialize the data members of the new object.
+When a [class](../../language-reference/keywords/class.md) or [struct](../../language-reference/builtin-types/struct.md) is instantiated, the runtime calls its constructor. Constructors have the same name as the class or struct, and they usually initialize the data members of the new object.
-In the following example, a class named `Taxi` is defined by using a simple constructor. This class is then instantiated with the [new](../../language-reference/operators/new-operator.md) operator. The `Taxi` constructor is invoked by the `new` operator immediately after memory is allocated for the new object.
+In the following example, a class named `Taxi` is defined by using a simple constructor. This class is then instantiated with the [`new`](../../language-reference/operators/new-operator.md) operator. The runtime invokes the `Taxi` constructor immediately after memory is allocated for the new object.
:::code source="./snippets/using-constructors/Program.cs" id="snippet1":::
-A constructor that takes no parameters is called a *parameterless constructor*. Parameterless constructors are invoked whenever an object is instantiated by using the `new` operator and no arguments are provided to `new`. C# 12 introduces *primary constructors*. A primary constructor specifies parameters that must be provided to initialize a new object. For more information, see [Instance Constructors](./instance-constructors.md).
+A constructor that takes no parameters is called a *parameterless constructor*. The runtime invokes the parameterless constructor when an object is instantiated using the `new` operator and no arguments are provided to `new`. C# 12 introduced *primary constructors*. A primary constructor specifies parameters that must be provided to initialize a new object. For more information, see [Instance Constructors](./instance-constructors.md).
Unless the class is [static](../../language-reference/keywords/static.md), classes without constructors are given a public parameterless constructor by the C# compiler in order to enable class instantiation. For more information, see [Static Classes and Static Class Members](./static-classes-and-static-class-members.md).
@@ -23,7 +23,7 @@ You can prevent a class from being instantiated by making the constructor privat
For more information, see [Private Constructors](./private-constructors.md).
-Constructors for [struct](../../language-reference/builtin-types/struct.md) types resemble class constructors. When a struct type is instantiated with `new`, a constructor is invoked. When a `struct` is set to its `default` value, the runtime initializes all memory in the struct to 0. If you declare any field initializers in a `struct` type, you must supply a parameterless constructor. For more information, see the [Struct initialization and default values](../../language-reference/builtin-types/struct.md#struct-initialization-and-default-values) section of the [Structure types](../../language-reference/builtin-types/struct.md) article.
+Constructors for [struct](../../language-reference/builtin-types/struct.md) types resemble class constructors. When a struct type is instantiated with `new`, the runtime invokes a constructor. When a `struct` is set to its `default` value, the runtime initializes all memory in the struct to 0. If you declare any field initializers in a `struct` type, you must supply a parameterless constructor. For more information, see the [Struct initialization and default values](../../language-reference/builtin-types/struct.md#struct-initialization-and-default-values) section of the [Structure types](../../language-reference/builtin-types/struct.md) article.
The following code uses the parameterless constructor for , so that you're assured that the integer is initialized:
@@ -32,14 +32,14 @@ int i = new int();
Console.WriteLine(i);
```
-The following code, however, causes a compiler error because it doesn't use `new`, and because it tries to use an object that hasn't been initialized:
+The following code, however, causes a compiler error because it doesn't use `new`, and because it tries to use an object that isn't initialized:
```csharp
int i;
Console.WriteLine(i);
```
-Alternatively, objects based on `structs` (including all built-in numeric types) can be initialized or assigned and then used as in the following example:
+Alternatively, some `struct` types (including all built-in numeric types) can be initialized or assigned and then used as in the following example:
```csharp
int a = 44; // Initialize the value type...
@@ -60,7 +60,7 @@ A constructor can use the `base` keyword to call the constructor of a base class
:::code source="./snippets/using-constructors/Program.cs" id="snippet5":::
-In this example, the constructor for the base class is called before the block for the constructor is executed. The `base` keyword can be used with or without parameters. Any parameters to the constructor can be used as parameters to `base`, or as part of an expression. For more information, see [base](../../language-reference/keywords/base.md).
+In this example, the constructor for the base class is called before the block for the constructor executes. The `base` keyword can be used with or without parameters. Any parameters to the constructor can be used as parameters to `base`, or as part of an expression. For more information, see [base](../../language-reference/keywords/base.md).
In a derived class, if a base-class constructor isn't called explicitly by using the `base` keyword, the parameterless constructor, if there's one, is called implicitly. The following constructor declarations are effectively the same:
@@ -70,17 +70,17 @@ In a derived class, if a base-class constructor isn't called explicitly by using
If a base class doesn't offer a parameterless constructor, the derived class must make an explicit call to a base constructor by using `base`.
-A constructor can invoke another constructor in the same object by using the [this](../../language-reference/keywords/this.md) keyword. Like `base`, `this` can be used with or without parameters, and any parameters in the constructor are available as parameters to `this`, or as part of an expression. For example, the second constructor in the previous example can be rewritten using `this`:
+A constructor can invoke another constructor in the same object by using the [`this`](../../language-reference/keywords/this.md) keyword. Like `base`, `this` can be used with or without parameters, and any parameters in the constructor are available as parameters to `this`, or as part of an expression. For example, the second constructor in the previous example can be rewritten using `this`:
:::code source="./snippets/using-constructors/Program.cs" id="snippet8":::
-The use of the `this` keyword in the previous example causes this constructor to be called:
+The use of the `this` keyword in the previous example causes the following constructor to be called:
:::code source="./snippets/using-constructors/Program.cs" id="snippet9":::
-Constructors can be marked as [public](../../language-reference/keywords/public.md), [private](../../language-reference/keywords/private.md), [protected](../../language-reference/keywords/protected.md), [internal](../../language-reference/keywords/internal.md), [protected internal](../../language-reference/keywords/protected-internal.md) or [private protected](../../language-reference/keywords/private-protected.md). These access modifiers define how users of the class can construct the class. For more information, see [Access Modifiers](./access-modifiers.md).
+Constructors can be marked as [`public`](../../language-reference/keywords/public.md), [`private`](../../language-reference/keywords/private.md), [`protected`](../../language-reference/keywords/protected.md), [internal](../../language-reference/keywords/internal.md), [protected internal](../../language-reference/keywords/protected-internal.md) or [`private protected`](../../language-reference/keywords/private-protected.md). These access modifiers define how users of the class can construct the class. For more information, see [Access Modifiers](./access-modifiers.md).
-A constructor can be declared static by using the [static](../../language-reference/keywords/static.md) keyword. Static constructors are called automatically, immediately before any static fields are accessed, and are used to initialize static class members. For more information, see [Static Constructors](./static-constructors.md).
+A constructor can be declared static by using the [`static`](../../language-reference/keywords/static.md) keyword. Static constructors are called automatically, before any static fields are accessed, and are used to initialize static class members. For more information, see [Static Constructors](./static-constructors.md).
## C# Language Specification
diff --git a/docs/csharp/tutorials/top-level-statements.md b/docs/csharp/tutorials/top-level-statements.md
index a01cd945ab1a7..ca6738e43cbaf 100644
--- a/docs/csharp/tutorials/top-level-statements.md
+++ b/docs/csharp/tutorials/top-level-statements.md
@@ -1,7 +1,7 @@
---
title: Top-level statements tutorial
description: This tutorial shows how you can use top-level statements to experiment and prove concepts while exploring your ideas
-ms.date: 11/22/2024
+ms.date: 01/15/2025
---
# Tutorial: Explore ideas using top-level statements to build code as you learn
@@ -47,7 +47,7 @@ Console.WriteLine("Hello, World!");
[!INCLUDE [csharp10-templates](../../../includes/csharp10-templates.md)]
-This feature simplifies what's needed to begin exploring new ideas. You can use top-level statements for scripting scenarios, or to explore. Once you've got the basics working, you can start refactoring the code and create methods, classes, or other assemblies for reusable components you built. Top-level statements do enable quick experimentation and beginner tutorials. They also provide a smooth path from experimentation to full programs.
+This feature simplifies your exploration of new ideas. You can use top-level statements for scripting scenarios, or to explore. Once you've got the basics working, you can start refactoring the code and create methods, classes, or other assemblies for reusable components you built. Top-level statements do enable quick experimentation and beginner tutorials. They also provide a smooth path from experimentation to full programs.
Top-level statements are executed in the order they appear in the file. Top-level statements can only be used in one source file in your application. The compiler generates an error if you use them in more than one file.
@@ -69,7 +69,7 @@ You can test your code by running the following `dotnet run` command:
dotnet run -- Should I use top level statements in all my programs?
```
-The arguments after the `--` on the command line are passed to the program. You can see the type of the `args` variable, because that's printed to the console:
+The arguments after the `--` on the command line are passed to the program. You can see the type of the `args` variable printed to the console:
```console
System.String[]
@@ -100,6 +100,8 @@ Should I use top level statements in all my programs?
Better not tell you now.
```
+The code to generate an answer includes a variable declaration in your top level statements. The compiler includes that declaration in the compiler generated `Main` method. Because these variable declarations are local variables, you can't include the `static` modifier.
+
This code answers the questions, but let's add one more feature. You'd like your question app to simulate thinking about the answer. You can do that by adding a bit of ASCII animation, and pausing while working. Add the following code after the line that echoes the question:
:::code language="csharp" source="snippets/top-level-statements/UtilitiesPassOne.cs" ID="AnimationFirstPass":::
diff --git a/docs/framework/install/run-net-framework-1-1-apps.md b/docs/framework/install/run-net-framework-1-1-apps.md
index e63eab3f3ff8b..88dc3d00e7409 100644
--- a/docs/framework/install/run-net-framework-1-1-apps.md
+++ b/docs/framework/install/run-net-framework-1-1-apps.md
@@ -10,7 +10,7 @@ ms.assetid: fb14e195-fea5-4561-b9a8-60a67283edb9
# Run .NET Framework 1.1 apps on Windows 8, Windows 8.1, Windows 10, or Windows 11
-.NET Framework 1.1 is not supported on the Windows 8, Windows 8.1, Windows Server 2012, Windows Server 2012 R2, Windows 10, or Windows 11 operating systems. In some cases, .NET Framework 1.1 is required for an app to run. In those cases, contact your independent software vendor (ISV) to have the app upgraded to run on .NET Framework 3.5 SP1 or a later version. For more information, see [Migrating from .NET Framework 1.1](../migration-guide/migrating-from-the-net-framework-1-1.md).
+.NET Framework 1.1 is not supported on the Windows 8, Windows 8.1, Windows Server 2012, Windows Server 2012 R2, Windows 10, or Windows 11 operating systems. In some cases, .NET Framework 1.1 is required for an app to run. In those cases, refer to the [Install .NET Framework 3.5 on Windows article](./dotnet-35-windows.md).
## Install .NET Framework 1.1 from a CD or download center
diff --git a/docs/framework/performance/garbage-collection-etw-events.md b/docs/framework/performance/garbage-collection-etw-events.md
index ca446cb35d4fb..5f2bde997ad54 100644
--- a/docs/framework/performance/garbage-collection-etw-events.md
+++ b/docs/framework/performance/garbage-collection-etw-events.md
@@ -266,7 +266,7 @@ The following table shows the keyword and level:
|Keyword for raising the event|Level|
|-----------------------------------|-----------|
-|`GCKeyword` (0x1)|Informational (4)|
+|`GCKeyword` (0x1)|Verbose (5)|
The following table shows the event information:
@@ -292,7 +292,7 @@ The following table shows the keyword and level:
|Keyword for raising the event|Level|
|-----------------------------------|-----------|
-|`GCKeyword` (0x1)|Informational (4)|
+|`GCKeyword` (0x1)|Verbose (5)|
The following table shows the event information:
diff --git a/docs/orleans/grains/grain-placement.md b/docs/orleans/grains/grain-placement.md
index 6e0f96d099cc6..2ebe3963a33f6 100644
--- a/docs/orleans/grains/grain-placement.md
+++ b/docs/orleans/grains/grain-placement.md
@@ -154,13 +154,7 @@ private static async Task StartSilo()
private static void ConfigureServices(IServiceCollection services)
{
- services.AddSingletonNamedService<
- PlacementStrategy, SamplePlacementStrategy>(
- nameof(SamplePlacementStrategy));
-
- services.AddSingletonKeyedService<
- Type, IPlacementDirector, SamplePlacementStrategyFixedSiloDirector>(
- typeof(SamplePlacementStrategy));
+ services.AddPlacementDirector();
}
```
diff --git a/docs/orleans/grains/timers-and-reminders.md b/docs/orleans/grains/timers-and-reminders.md
index 1fbf828d2dcf8..d21b9308afe40 100644
--- a/docs/orleans/grains/timers-and-reminders.md
+++ b/docs/orleans/grains/timers-and-reminders.md
@@ -10,19 +10,19 @@ The Orleans runtime provides two mechanisms, called timers and reminders, that e
## Timers
-**Timers** are used to create periodic grain behavior that isn't required to span multiple activations (instantiations of the grain). A timer is identical to the standard .NET class. In addition, timers are subject to single-threaded execution guarantees within the grain activation that they operate on, and their executions are interleaved with other requests, as though the timer callback was a grain method marked with .
+**Timers** are used to create periodic grain behavior that isn't required to span multiple activations (instantiations of the grain). A timer is identical to the standard .NET class. In addition, timers are subject to single-threaded execution guarantees within the grain activation that they operate on.
Each activation may have zero or more timers associated with it. The runtime executes each timer routine within the runtime context of the activation that it's associated with.
## Timer usage
-To start a timer, use the `RegisterGrainTimer` method, which returns an reference:
+To start a timer, use the `RegisterGrainTimer` method, which returns an reference:
```csharp
-protected IDisposable RegisterGrainTimer(
- Func callback, // function invoked when the timer ticks
- object state, // object to pass to callback
- GrainTimerCreationOptions options) // timer creation options
+protected IGrainTimer RegisterGrainTimer(
+ Func callback, // function invoked when the timer ticks
+ TState state, // object to pass to callback
+ GrainTimerCreationOptions options) // timer creation options
```
To cancel the timer, you dispose of it.
@@ -33,7 +33,15 @@ A timer ceases to trigger if the grain is deactivated or when a fault occurs and
* When activation collection is enabled, the execution of a timer callback doesn't change the activation's state from idle to in-use. This means that a timer can't be used to postpone the deactivation of otherwise idle activations.
* The period passed to `Grain.RegisterGrainTimer` is the amount of time that passes from the moment the `Task` returned by `callback` is resolved to the moment that the next invocation of `callback` should occur. This not only makes it impossible for successive calls to `callback` to overlap, but also makes it so that the length of time `callback` takes to complete affects the frequency at which `callback` is invoked. This is an important deviation from the semantics of .
-* Each invocation of `callback` is delivered to an activation on a separate turn, and never runs concurrently with other turns on the same activation. However, `callback` invocations aren't delivered as messages and thus aren't subject to message interleaving semantics. This means that invocations of `callback` behave as if the grain is re-entrant and executes concurrently with other grain requests. In order to use the grain's request scheduling semantics, you can call a grain method to perform the work you would have done within `callback`. Another alternative is to use an `AsyncLock` or a . A more detailed explanation is available in [Orleans GitHub issue #2574](https://github.com/dotnet/orleans/issues/2574).
+* Each invocation of `callback` is delivered to an activation on a separate turn, and never runs concurrently with other turns on the same activation.
+* Callbacks do not interleave by default. Interleaving can be enabled by setting Interleave to true on GrainTimerCreationOptions.
+* Grain timers can be updated using the Change(TimeSpan, TimeSpan) method on the returned IGrainTimer instance.
+* Callbacks can keep the grain active, preventing it from being collected if the timer period is relatively short. This can be enabled by setting KeepAlive to true on GrainTimerCreationOptions.
+* Callbacks can receive a CancellationToken which is canceled when the timer is disposed or the grain starts to deactivate.
+* Callbacks can dispose the grain timer which fired them.
+* Callbacks are subject to grain call filters.
+* Callbacks are visible in distributed tracing, when distributed tracing is enabled.
+* POCO grains (grain classes which do not inherit from Grain) can register grain timers using the RegisterGrainTimer extension method.
## Reminders
diff --git a/docs/visual-basic/developing-apps/programming/drives-directories-files/how-to-rename-a-file.md b/docs/visual-basic/developing-apps/programming/drives-directories-files/how-to-rename-a-file.md
index 48d65fca60408..8310371fdbd3f 100644
--- a/docs/visual-basic/developing-apps/programming/drives-directories-files/how-to-rename-a-file.md
+++ b/docs/visual-basic/developing-apps/programming/drives-directories-files/how-to-rename-a-file.md
@@ -1,7 +1,7 @@
---
title: "How to: Rename a File"
description: "Learn about how to rename a file with the Visual Basic Runtime Library or the .NET base class library."
-ms.date: 07/20/2015
+ms.date: 01/14/2025
helpviewer_keywords:
- "I/O [Visual Basic], renaming files"
- "files [Visual Basic], renaming"
@@ -17,7 +17,7 @@ The `System.IO.File` object doesn't contain a method to rename a file, instead,
The following example renames the file located in the `My Documents` folder from `TextFile.txt` to `NewName.txt`.
-:::code language="csharp" source="./snippets/how-to-rename-a-file/Form1.vb" id="BCLRename":::
+:::code language="vb" source="./snippets/how-to-rename-a-file/Form1.vb" id="BCLRename":::
## Rename with the Visual Basic run-time
@@ -25,7 +25,7 @@ Use the `RenameFile` method of the `My.Computer.FileSystem` object to rename a f
The following example renames the file located in the `My Documents` folder from `TextFile.txt` to `NewName.txt`.
-:::code language="csharp" source="./snippets/how-to-rename-a-file/Form1.vb" id="MyRename":::
+:::code language="vb" source="./snippets/how-to-rename-a-file/Form1.vb" id="MyRename":::
Visual Studio provides an IntelliSense code snippet that uses `My.Computer.FileSystem.RenameFile`. The snippet is located in **File system - Processing Drives, Folders, and Files**. For more information, see [Code Snippets](/visualstudio/ide/code-snippets).