diff --git a/docs/core/extensions/httpclient-latency-extensions.md b/docs/core/extensions/httpclient-latency-extensions.md new file mode 100644 index 0000000000000..fddcc71db31b5 --- /dev/null +++ b/docs/core/extensions/httpclient-latency-extensions.md @@ -0,0 +1,139 @@ +--- +title: Monitor and analyze HTTP client performance +description: Learn how to use the HttpClientLatency with dependency injection in your .NET workloads. +author: IEvangelist +ms.author: dapine +ms.date: 09/29/2025 +ai-usage: ai-assisted +--- + +# HTTP client latency telemetry in .NET + +When you build applications that communicate over HTTP, it's important to observe request performance characteristics. +The +extension enables collection of detailed timing information for outgoing HTTP calls with no changes to calling code. +It plugs into the existing `HttpClientFactory` pipeline to capture stage timings across the request lifecycle, record +HTTP protocol details, measure garbage collection impact where the runtime exposes that data, and emit a uniform +telemetry shape suitable for performance analysis and tuning.Enable them by calling `AddHttpClientLatencyTelemetry()` extension method. +The built‑in handler creates an `ILatencyContext` per outbound request and populates measures by the time the inner +pipeline completes. Consume them after `await base.SendAsync(...)` in a later delegating handler (added after telemetry) +and export to your metrics backend. Example: + +Register extension method: + +:::code language="csharp" source="snippets/http/latency/RegisterHandler.cs" range="3-24" highlight="11"::: + +Access the context: + +:::code language="csharp" source="snippets/http/latency/HttpLatencyExportHandler.cs" range="4-23" highlight="12,15"::: + +### [.NET CLI](#tab/dotnet-cli) + +```dotnetcli +dotnet add package Microsoft.Extensions.Http.Diagnostics --version 9.10.0 +``` + +### [PackageReference](#tab/package-reference) + +```xml + +``` + +--- + +For more information, see [dotnet package add](../tools/dotnet-package-add.md) or [Manage package dependencies in .NET applications](../tools/dependencies.md). + +### Register HTTP client latency telemetry + +To add HTTP client latency telemetry to your application, call the extension method when configuring your services: + +:::code language="csharp" source="snippets/http/latency/Program.cs" id="extensions" highlight="7"::: + +This registration adds a `DelegatingHandler` to all HTTP clients created through , collecting detailed latency information for each request. + +### Configure telemetry options + +You configure telemetry collection through the ([standard options pattern](https://learn.microsoft.com/dotnet/core/extensions/options)). +You can supply values either with a delegate or by binding configuration (for example, `appsettings.json`). +The options instance is resolved once per handler pipeline so changes apply to new clients/handlers. + +:::code language="csharp" source="snippets/http/latency/Program.cs" range="23-31" highlight="1-5,8,9"::: + +### Configuration options + +The class offers the following settings: + +| Option | Type | Default | Description | When to disable | +|--------------------------------|---------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------| +| EnableDetailedLatencyBreakdown | Boolean | `true` | Enables fine-grained phase timing for each HttpClient request (for example, connection establishment, headers sent, first byte, completion) to produce a breakdown of total latency. Adds a small extra CPU/time measurement cost, no wire overhead. | Set to `false` only in very high-throughput scenarios where minimal overhead is required and total duration alone is sufficient. | + +### Collected telemetry data + +When HTTP client latency telemetry is enabled, it captures phase timestamps, selected measures (where supported), and protocol attributes used for performance analysis. + +#### Timing checkpoints + +Timestamps are recorded for key stages of the HTTP request lifecycle: + +| Phase | Start Event | End Event | Notes | +|-------------------------|----------------------------|----------------------------|---------------------------------------------------------| +| DNS resolution | Http.NameResolutionStart | Http.NameResolutionEnd | Host name lookup (may be cached and skipped). | +| Socket connection | Http.SocketConnectStart | Http.SocketConnectEnd | CP (and TLS handshake if combined by handler). | +| Connection establishment| | Http.ConnectionEstablished | Marks usable connection after handshake. | +| Request headers | Http.RequestHeadersStart | Http.RequestHeadersEnd | Writing request headers to the wire/buffer. | +| Request content | Http.RequestContentStart | Http.RequestContentEnd | Streaming or buffering request body. | +| Response headers | Http.ResponseHeadersStart | Http.ResponseHeadersEnd | First byte to completion of header parsing. | +| Response content | Http.ResponseContentStart | Http.ResponseContentEnd | Reading full response body (to completion or disposal). | + +#### Measures (platform dependent) + +Measures quantify latency contributors that raw phase checkpoints cannot (GC pause overlap, connection churn, other +accumulated counts or durations). They are collected in an in‑memory latency context created when you call +`AddHttpClientLatencyTelemetry()`. Nothing is emitted automatically: the context simply accumulates checkpoints, measures, +and tags until the request completes. If you also enable HTTP client logging enrichment with `AddExtendedHttpClientLogging()`, +the completed context is flattened into a single structured log field named `LatencyInfo` (version marker, server name if available, then tag, checkpoint, and measure name/value sequences). + +That log field is the only built‑in output artifact; no metrics or traces are produced unless you add your own exporter. +To surface them as metrics, read the context after the request pipeline returns and record (for example) GC pause overlap +to a histogram and connection initiations to a counter, optionally dimensioned by protocol version. + +| Name | Description | +|--------------------------|-------------------------------------------------------------------------| +| Http.GCPauseTime | Total GC pause duration overlapping the request. | +| Http.ConnectionInitiated | Emitted when a new underlying connection (not pooled reuse) is created. | + +#### Tags + +Use tags to attach stable categorical dimensions to each request so you can segment, filter, and aggregate metrics +and logs without reprocessing raw data. They are low‑cardinality classification labels (not timings) captured +in the latency context and, if HTTP client log enrichment is enabled, serialized into a single LatencyInfo log field. +Enable enrichment at application startup by adding the logging extension (for all clients or per client) along with +latency telemetry, for example: + +:::code language="csharp" source="snippets/http/latency/Program.cs" range="36-39" highlight="2,3"::: + +After this, outbound requests logged through the structured logging pipeline will include the `LatencyInfo` property +containing the flattened tags, checkpoints, and measures. No metrics or traces are emitted automatically for tags; +export them yourself (e.g., turn tag values into metric dimensions or `Activity` tags) if you need them outside logs. + +| Tag | Description | +|--------------|-----------------------------------------------------------------| +| Http.Version | HTTP protocol version negotiated/used (for example, 1.1, 2, 3). | + +## Usage example + +These components enable tracking and reporting the latency of HTTP client request processing. + +You can register the services using the following methods: + +:::code language="csharp" source="snippets/http/latency/Program.cs" range="44-53" highlight="1,2,4-6, 8-10"::: + +For example: + +:::code language="csharp" source="snippets/http/latency/Program.cs" range="58-75" highlight="10,13,16"::: + +### Platform considerations + +HTTP client latency telemetry runs on all supported targets (.NET 9, .NET 8, .NET Standard 2.0, and .NET Framework 4.6.2). +Core timing checkpoints are always collected. The GC pause metric (Http.GCPauseTime) is emitted only when running on .NET 8 or .NET 9. +The implementation detects platform capabilities at run time and enables what is supported without additional configuration. diff --git a/docs/core/extensions/snippets/http/latency/HttpLatencyExportHandler.cs b/docs/core/extensions/snippets/http/latency/HttpLatencyExportHandler.cs new file mode 100644 index 0000000000000..a5c72e42294e4 --- /dev/null +++ b/docs/core/extensions/snippets/http/latency/HttpLatencyExportHandler.cs @@ -0,0 +1,23 @@ +namespace GeneratedHttp.Example; + + +public sealed class HttpLatencyExportHandler : DelegatingHandler +{ + // ILatencyContextAccessor is just an example of some accessor that is able to read latency context + private readonly ILatencyContextAccessor _latency; + + public HttpLatencyExportHandler(ILatencyContextAccessor latency) => _latency = latency; + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken ct) + { + var rsp = await base.SendAsync(request, ct).ConfigureAwait(false); + + var ctx = _latency.Current; + if (ctx != null) + { + var data = ctx.LatencyData; + // Record/export gc and conn with version as a dimension here. + } + return rsp; + } +} diff --git a/docs/core/extensions/snippets/http/latency/Program.cs b/docs/core/extensions/snippets/http/latency/Program.cs new file mode 100644 index 0000000000000..622fdc1bd2d73 --- /dev/null +++ b/docs/core/extensions/snippets/http/latency/Program.cs @@ -0,0 +1,77 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Http.Diagnostics; + + +internal class Program +{ + private static void ConfigureHttpClientLatency(HostApplicationBuilder builder) + { + // + var builder = WebApplication.CreateBuilder(args); + + // Add HTTP client factory + builder.Services.AddHttpClient(); + + // Add HTTP client latency telemetry + builder.Services.AddHttpClientLatencyTelemetry(); + // + } + + private static void ConfigureWithDelegate(HostApplicationBuilder builder) + { + // Configure with delegate + builder.Services.AddHttpClientLatencyTelemetry(options => + { + options.EnableDetailedLatencyBreakdown = true; + }); + + // Or configure from configuration + builder.Services.AddHttpClientLatencyTelemetry( + builder.Configuration.GetSection("HttpClientTelemetry")); + } + + private static void EnableLatencyContext(HostApplicationBuilder builder) + { + var builder = Host.CreateApplicationBuilder(args); + builder.Services.AddHttpClientLatencyTelemetry(); // enables latency context + measures/tags + builder.Services.AddExtendedHttpClientLogging(); + var app = builder.Build(); + } + + private static void RegistrationOptions(HostApplicationBuilder builder) + { + public static IServiceCollection AddHttpClientLatencyTelemetry( + this IServiceCollection services); + + public static IServiceCollection AddHttpClientLatencyTelemetry( + this IServiceCollection services, + IConfigurationSection section); + + public static IServiceCollection AddHttpClientLatencyTelemetry( + this IServiceCollection services, + Action configure); + } + + private static void HttpClientLatency(HostApplicationBuilder builder) + { + var builder = Host.CreateApplicationBuilder(args); + + // Register IHttpClientFactory: + builder.Services.AddHttpClient(); + + // Register redaction services: + builder.Services.AddRedaction(); + + // Register latency context services: + builder.Services.AddLatencyContext(); + + // Register HttpClient logging enrichment & redaction services: + builder.Services.AddExtendedHttpClientLogging(); + + // Register HttpClient latency telemetry services: + builder.Services.AddHttpClientLatencyTelemetry(); + + var host = builder.Build(); + } +} diff --git a/docs/core/extensions/snippets/http/latency/RegisterHandler.cs b/docs/core/extensions/snippets/http/latency/RegisterHandler.cs new file mode 100644 index 0000000000000..11765ce497d68 --- /dev/null +++ b/docs/core/extensions/snippets/http/latency/RegisterHandler.cs @@ -0,0 +1,24 @@ +namespace GeneratedHttp.Example; + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Http.Diagnostics; +using Microsoft.Extensions.Hosting; + +var builder = Host.CreateApplicationBuilder(args); + +// An example of some accessor that is able to read latency context +builder.Services.AddSingleton(); + +// Register HTTP client latency telemetry first so its delegating handler runs earlier. +builder.Services.AddHttpClientLatencyTelemetry(); + +// Register export handler (runs after telemetry; sees finalized ILatencyContext). +builder.Services.AddTransient(); + +// Register an HttpClient that will emit and export latency measures. +builder.Services + .AddHttpClient("observed") + .AddHttpMessageHandler(); + +var host = builder.Build(); +await host.RunAsync(); diff --git a/docs/core/extensions/snippets/http/latency/latency.csproj b/docs/core/extensions/snippets/http/latency/latency.csproj new file mode 100644 index 0000000000000..fe0f3f86f9a2d --- /dev/null +++ b/docs/core/extensions/snippets/http/latency/latency.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + true + Exe + + + + + + + + + Always + + + + + + + + diff --git a/docs/csharp/language-reference/compiler-messages/extension-declarations.md b/docs/csharp/language-reference/compiler-messages/extension-declarations.md index 4185b5634e9fb..6e0b9bb66c72a 100644 --- a/docs/csharp/language-reference/compiler-messages/extension-declarations.md +++ b/docs/csharp/language-reference/compiler-messages/extension-declarations.md @@ -1,7 +1,7 @@ --- title: "Errors and warnings related to extension declarations" description: "These errors and warnings indicate that you need to modify the declaration of an extension method using the `this` modifier on the first parameter, or an extension declaration" -ms.date: 05/23/2025 +ms.date: 10/16/2025 f1_keywords: - "CS1100" - "CS1101" @@ -32,6 +32,18 @@ f1_keywords: - "CS9303" - "CS9304" - "CS9305" + - "CS9306" + - "CS9309" + - "CS9316" + - "CS9317" + - "CS9318" + - "CS9319" + - "CS9320" + - "CS9321" + - "CS9322" + - "CS9323" + - "CS9326" + - "CS9329" helpviewer_keywords: - "CS1100" - "CS1101" @@ -64,6 +76,18 @@ helpviewer_keywords: - "CS9303" - "CS9304" - "CS9305" + - "CS9306" + - "CS9309" + - "CS9316" + - "CS9317" + - "CS9318" + - "CS9319" + - "CS9320" + - "CS9321" + - "CS9322" + - "CS9323" + - "CS9326" + - "CS9329" --- # Errors and warnings related to extension methods declared with `this` parameters or `extension` blocks @@ -98,6 +122,18 @@ helpviewer_keywords: - [**CS9303**](#errors-related-to-extension-block-declarations): *Cannot declare instance members in an extension block with an unnamed receiver parameter.* - [**CS9304**](#errors-related-to-extension-block-declarations): *Cannot declare init-only accessors in an extension block.* - [**CS9305**](#errors-related-to-extension-block-declarations): *Cannot use modifiers on the unnamed receiver parameter of extension block.* +- [**CS9306**](#errors-related-to-extension-block-declarations): *Types and aliases cannot be named 'extension'.* +- [**CS9309**](#errors-related-to-extension-block-declarations): *An extension member syntax is disallowed in nested position within an extension member syntax.* +- [**CS9316**](#errors-related-to-extension-block-declarations): *Extension members are not allowed as an argument to '`nameof`'.* +- [**CS9317**](#errors-related-to-extension-block-declarations): *The parameter of a unary operator must be the extended type.* +- [**CS9318**](#errors-related-to-extension-block-declarations): *The parameter type for ++ or -- operator must be the extended type.* +- [**CS9319**](#errors-related-to-extension-block-declarations): *One of the parameters of a binary operator must be the extended type.* +- [**CS9320**](#errors-related-to-extension-block-declarations): *The first operand of an overloaded shift operator must have the same type as the extended type.* +- [**CS9321**](#errors-related-to-extension-block-declarations): *An extension block extending a static class cannot contain user-defined operators.* +- [**CS9322**](#errors-related-to-extension-block-declarations): *Cannot declare instance operator for a struct unless containing extension block receiver parameter is a '`ref`' parameter.* +- [**CS9323**](#errors-related-to-extension-block-declarations): *Cannot declare instance extension operator for a type that is not known to be a struct and is not known to be a class.* +- [**CS9326**](#errors-related-to-extension-block-declarations): *'`name`': extension member names cannot be the same as their extended type.* +- [**CS9329**](#errors-related-to-extension-block-declarations): *This extension block collides with another extension block. They result in conflicting content-based type names in metadata.* ## Common errors on extension declarations @@ -143,6 +179,20 @@ These errors are specific to extension blocks, a C# 14 feature. Extension blocks - **CS9303**: *Cannot declare instance members in an extension block with an unnamed receiver parameter.* - **CS9304**: *Cannot declare init-only accessors in an extension block.* - **CS9305**: *Cannot use modifiers on the unnamed receiver parameter of extension block.* +- **CS9306**: *Types and aliases cannot be named 'extension'.* +- **CS9309**: *An extension member syntax is disallowed in nested position within an extension member syntax.* +- **CS9316**: *Extension members are not allowed as an argument to '`nameof`'.* +- **CS9317**: *The parameter of a unary operator must be the extended type.* +- **CS9318**: *The parameter type for ++ or -- operator must be the extended type.* +- **CS9319**: *One of the parameters of a binary operator must be the extended type.* +- **CS9320**: *The first operand of an overloaded shift operator must have the same type as the extended type.* +- **CS9321**: *An extension block extending a static class cannot contain user-defined operators.* +- **CS9322**: *Cannot declare instance operator for a struct unless containing extension block receiver parameter is a '`ref`' parameter.* +- **CS9323**: *Cannot declare instance extension operator for a type that is not known to be a struct and is not known to be a class.* +- **CS9326**: *'`name`': extension member names cannot be the same as their extended type.* +- **CS9329**: *This extension block collides with another extension block. They result in conflicting content-based type names in metadata.* + +The contextual keyword [`extension`](../keywords/extension.md) declares an extension block. It can't be used for a type. Extension declarations must follow these rules: @@ -155,6 +205,23 @@ Extension members declared in an extension block must follow these rules, in add - The extension must provide a parameter name for the receiver in order to contain members that extend an instance. - The receiver parameter name must be unique in that extension block. - All extension members must use all type parameters declared on the extension. They can add more type parameters. +- Extension blocks can't be nested within another extension block. + +**CS9316** is emitted when you attempt to use an extension member as an argument to the `nameof` operator. Extension members aren't allowed in this context. + +**CS9317**, **CS9318**, **CS9319**, **CS9320**, **CS9321**, **CS9322**, and **CS9323** are operator-related errors in extension blocks: + +- **CS9317**: Unary operators must have the extended type as their parameter. +- **CS9318**: Increment (`++`) and decrement (`--`) operators must have the extended type as their parameter. +- **CS9319**: Binary operators must have at least one parameter that is the extended type. +- **CS9320**: Shift operators must have the extended type as their first operand. +- **CS9321**: You can't declare user-defined operators in extension blocks that extend static classes. +- **CS9322**: When extending a struct with instance operators, the receiver parameter must use the `ref` modifier. +- **CS9323**: You can't declare instance operators for types that aren't constrained to be either a struct or a class. + +**CS9326** is emitted when an extension member has the same name as the extended type. Choose a different name for the member. + +**CS9329** occurs when two extension blocks result in conflicting content-based type names in the compiled metadata. This typically happens when multiple extension blocks with the same receiver type and similar characteristics are declared. Consolidate the extension blocks or differentiate them in a way that produces unique metadata names. ## Errors related to `this` parameter extension methods diff --git a/docs/csharp/language-reference/compiler-messages/pattern-matching-warnings.md b/docs/csharp/language-reference/compiler-messages/pattern-matching-warnings.md index bbb3d9717edb7..2c0e6f799ad52 100644 --- a/docs/csharp/language-reference/compiler-messages/pattern-matching-warnings.md +++ b/docs/csharp/language-reference/compiler-messages/pattern-matching-warnings.md @@ -5,11 +5,14 @@ f1_keywords: - "CS8509" # WRN_SwitchNotAllPossibleValues: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '...' is not covered. - "CS9134" - "CS9135" + - "CS9335" + - "CS9337" helpviewer_keywords: - "CS8509" - "CS9134" - - "CS9135" -ms.date: 11/02/2022 + - "CS9335" + - "CS9337" +ms.date: 10/16/2025 --- # Pattern matching errors and warnings @@ -17,6 +20,8 @@ The compiler generates the following errors for invalid pattern match expression - **CS9134**: *A switch expression arm does not begin with a 'case' keyword.* - **CS9135**: *A constant value of type is expected* +- **CS9335**: *The pattern is redundant.* +- **CS9337**: *The pattern is too complex to analyze for redundancy.* The compiler generates the following warnings for incomplete pattern matching expressions: @@ -45,4 +50,12 @@ To address this warning, add switch arms that cover all possible input values. F The `_` pattern matches all remaining values. One scenario for the `_` pattern is matching invalid values, as shown in the preceding example. +The compiler generates CS9335 when you wrote a pattern where an `or` is redundant: + +:::code language="csharp" source="./snippets/pattern-matching-warnings/Switch.cs" id="RedundantPattern"::: + +This warning indicates you likely meant `is not (null or 42)` or `is not (int or string)` instead. + +You can construct patterns that are too complex to analyze for redundancy. If you do that, the compiler warns you with CS9337. + For more information, see [Switch](../statements/selection-statements.md#the-switch-statement). diff --git a/docs/csharp/language-reference/compiler-messages/snippets/pattern-matching-warnings/Switch.cs b/docs/csharp/language-reference/compiler-messages/snippets/pattern-matching-warnings/Switch.cs index ba2051ade87ca..9a2f9b74c66fe 100644 --- a/docs/csharp/language-reference/compiler-messages/snippets/pattern-matching-warnings/Switch.cs +++ b/docs/csharp/language-reference/compiler-messages/snippets/pattern-matching-warnings/Switch.cs @@ -21,6 +21,15 @@ void Method(EnumValues enumValues) }; } // + + public static void RedundantPattern() + { + object? o = null; + // + _ = o is not null or 42; // warning: pattern "42" is redundant + _ = o is not int or string; // warning: pattern "string" is redundant + // + } } } diff --git a/docs/csharp/language-reference/operators/member-access-operators.md b/docs/csharp/language-reference/operators/member-access-operators.md index f86f54f164c6b..9dda13cf2fd61 100644 --- a/docs/csharp/language-reference/operators/member-access-operators.md +++ b/docs/csharp/language-reference/operators/member-access-operators.md @@ -155,7 +155,7 @@ Beginning in C# 14, assignment is permissible with a null conditional access exp The preceding example shows assignment to a property and an indexed element on a reference type that might be null. An important behavior for this assignment is that the expression on the right-hand side of the `=` is evaluated only when the left-hand side is known to be non-null. For example, in the following code, the function `GenerateNextIndex` is called only when the `values` array isn't null. If the `values` array is null, `GenerateNextIndex` isn't called: -:::code language="csharp" source="snippets/shared/NullCoalescingOperator.cs" id="NullForgivingAssignment"::: +:::code language="csharp" source="snippets/shared/NullCoalescingOperator.cs" id="ConditionalRHS"::: In other words, the preceding code is equivalent to the following code using an `if` statement for the null check: diff --git a/docs/csharp/language-reference/toc.yml b/docs/csharp/language-reference/toc.yml index 92f54bc76877b..3b1858ef70716 100644 --- a/docs/csharp/language-reference/toc.yml +++ b/docs/csharp/language-reference/toc.yml @@ -520,7 +520,8 @@ items: displayName: > CS1100, CS1101, CS1102, CS1103, CS1105, CS1106, CS1109, CS1110, CS1113, CS1112, CS1100, CS1101, CS1102, CS1103, CS1105, CS1106, CS1109, CS1110, CS1112, CS1113, CS1754, CS9281, CS9282, CS9283, CS9284, CS9285, CS9287, CS9288, - CS9289, CS9290, CS9292, CS9293, CS9295, CS9300, CS9301, CS9302, CS9303, CS9304, CS9305 + CS9289, CS9290, CS9292, CS9293, CS9295, CS9300, CS9301, CS9302, CS9303, CS9304, CS9305, CS9306, CS9309, CS9316, + CS9317, CS9318, CS9319, CS9320, CS9321, CS9322, CS9323, CS9326, CS9329 - name: Partial declarations href: ./compiler-messages/partial-declarations.md displayName: > @@ -543,7 +544,7 @@ items: CS8768, CS8670, CS8714, CS8767, CS8769, CS8770, CS8774, CS8776, CS8775, CS8777, CS8819, CS8824, CS8825, CS8847 - name: Pattern matching warnings href: ./compiler-messages/pattern-matching-warnings.md - displayName: CS8509, CS9134, CS9135 + displayName: CS8509, CS9134, CS9135, CS9335, CS9337 - name: String literal declarations href: ./compiler-messages/string-literal.md displayName: > @@ -574,7 +575,7 @@ items: displayName: > CS0765, CS0831, CS0832, CS0834, CS0835, CS0838, CS0845, CS0853, CS0854, CS0855, CS1944, CS1945, CS1946, CS1951, CS1952, CS1963, CS2037, CS7053, CS8072, CS8074, CS8075, CS8110, CS8122, CS8143, CS8144, CS8153, CS8155, CS8198, CS8207, CS8382, - CS8514, CS8640, CS8642, CS8790, CS8791, CS8792, CS8810, CS8849, CS8927, CS8952, CS9170, CS9175 + CS8514, CS8640, CS8642, CS8790, CS8791, CS8792, CS8810, CS8849, CS8927, CS8952, CS9170, CS9175, CS9307 - name: Using directive and aliases href: ./compiler-messages/using-directive-errors.md displayName: > diff --git a/docs/csharp/misc/sorry-we-don-t-have-specifics-on-this-csharp-error.md b/docs/csharp/misc/sorry-we-don-t-have-specifics-on-this-csharp-error.md index c8f5d9aece3ea..59076a4fed587 100644 --- a/docs/csharp/misc/sorry-we-don-t-have-specifics-on-this-csharp-error.md +++ b/docs/csharp/misc/sorry-we-don-t-have-specifics-on-this-csharp-error.md @@ -593,22 +593,14 @@ f1_keywords: - "CS9235" - "CS9236" # C# 14 errors begin here -## using `extension` as type name. (valid identifiers). - - "CS9306" -## More extension errors - - "CS9316" - - "CS9317" - - "CS9318" - - "CS9319" - - "CS9326" - "CS9327" - "CS9328" - - "CS9329" - "CS9330" - "CS9331" - "CS9332" - "CS9333" - "CS9334" + - "CS9338" helpviewer_keywords: - "errors [C#], additional information" --- diff --git a/docs/csharp/programming-guide/classes-and-structs/how-to-initialize-a-dictionary-with-a-collection-initializer.md b/docs/csharp/programming-guide/classes-and-structs/how-to-initialize-a-dictionary-with-a-collection-initializer.md index 5c3964c36d593..0c8ad5f7da47f 100644 --- a/docs/csharp/programming-guide/classes-and-structs/how-to-initialize-a-dictionary-with-a-collection-initializer.md +++ b/docs/csharp/programming-guide/classes-and-structs/how-to-initialize-a-dictionary-with-a-collection-initializer.md @@ -1,11 +1,12 @@ --- title: "How to initialize a dictionary with a collection initializer" description: Learn how to initialize a dictionary in C#, using either the Add method or an index initializer. This example shows both options. -ms.date: 02/12/2025 +ms.date: 10/14/2025 helpviewer_keywords: - "collection initializers [C#], with Dictionary" ms.topic: how-to ms.assetid: 25283922-f8ee-40dc-a639-fac30804ec71 +ms.custom: copilot-scenario-highlight --- # How to initialize a dictionary with a collection initializer (C# Programming Guide) @@ -30,6 +31,25 @@ In the following code example, a . Finally, the whole collection initializer for the dictionary is enclosed in braces. In the second initialization, the left side of the assignment is the key and the right side is the value, using an object initializer for `StudentName`. +## Use AI to generate test data for dictionary collections + +You can use AI tools, such as GitHub Copilot, to quickly generate dictionary test data and validation scenarios in your C# projects. + +Here's an example prompt you can use in Visual Studio Copilot Chat. + +```copilot-prompt +Generate data collections for tests to create a separate Dictionary containing 10 valid Student records and 5 invalid records. +- Valid records should have realistic Name and Grade values. +- Invalid records should include cases such as missing Name, Grade < 0, or Grade > 100. +- This dictionary should be used only for testing purposes and not modify existing production code. +- Generate test code that utilizes this test data for validation scenarios. +- Call test method to run the test. +``` + +Review Copilot's suggestions before applying them. + +For more information about GitHub Copilot, see GitHub's [FAQs](https://github.com/features/copilot#faq). + ## See also - [Object and Collection Initializers](./object-and-collection-initializers.md) diff --git a/docs/fundamentals/toc.yml b/docs/fundamentals/toc.yml index 5fd27bcf17177..7b74f1965d772 100644 --- a/docs/fundamentals/toc.yml +++ b/docs/fundamentals/toc.yml @@ -1139,6 +1139,9 @@ items: - name: HTTP client factory href: ../core/extensions/httpclient-factory.md displayName: networking,httpclient,http,dependency injection,client,factory,named client,named httpclient,typed client,typed httpclient + - name: Monitor and analyze HTTP client performance + href: ../core/extensions/httpclient-latency-extensions.md + displayName: httpclient,http,client,factory,dependency injection,keyed,keyed di,keyed services - name: HTTP client factory troubleshooting href: ../core/extensions/httpclient-factory-troubleshooting.md displayName: httpclient,http,client,factory,named client,named httpclient,typed client,typed httpclient