From ca0e8d422df3a2ce7a6a3b673d1305374a347a13 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 29 Sep 2025 22:44:21 -0400 Subject: [PATCH] Re-enable IDE0032 --- src/Libraries/.editorconfig | 6 +- .../ChatCompletion/ChatFinishReason.cs | 7 +- .../ChatCompletion/ChatResponseUpdate.cs | 7 +- .../Contents/DataContent.cs | 1 + .../Contents/ErrorContent.cs | 9 +- .../Contents/TextContent.cs | 8 +- .../Contents/TextReasoningContent.cs | 8 +- .../Embeddings/EmbeddingGenerationOptions.cs | 6 +- .../Image/ImageGenerationResponse.cs | 9 +- .../AzureStorageJsonUtilities.cs | 6 +- .../CSharp/JsonSerialization/JsonUtilities.cs | 6 +- .../ContentSafetyService.cs | 13 +- .../DistributedCachingChatClient.cs | 27 ++-- .../FunctionInvocationContext.cs | 32 ++--- .../FunctionInvokingChatClient.cs | 27 ++-- .../ChatReduction/SummarizingChatReducer.cs | 10 +- .../ManualHealthCheck.cs | 6 +- .../Polly/HttpRetryStrategyOptions.cs | 8 +- .../Routing/UriEndpoint.cs | 10 +- .../Logging/LoggerMessageHelper.cs | 19 +-- .../Latency/Internal/CheckpointTracker.cs | 13 +- .../Latency/Internal/LatencyContext.cs | 10 +- .../Logging/ExtendedLogger.LegacyTagJoiner.cs | 11 +- .../Logging/ExtendedLogger.ThreadLocals.cs | 40 +----- .../FakeTimeProvider.cs | 7 +- src/Shared/.editorconfig | 6 +- .../JsonSchemaExporter.JsonSchema.cs | 122 ++++++------------ src/Shared/ServerSentEvents/SseItem.cs | 14 +- test/.editorconfig | 2 +- .../HeaderParsingFeatureTests.cs | 7 +- .../Settings.cs | 11 +- .../Settings.cs | 11 +- .../Infrastructure/Project.cs | 21 +-- .../Infrastructure/TestCommandResult.cs | 7 +- 34 files changed, 166 insertions(+), 341 deletions(-) diff --git a/src/Libraries/.editorconfig b/src/Libraries/.editorconfig index d3164bd9547..d33ed319482 100644 --- a/src/Libraries/.editorconfig +++ b/src/Libraries/.editorconfig @@ -2012,7 +2012,7 @@ dotnet_style_null_propagation = true # Title : Use auto property # Category : Style # Help Link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0032 -dotnet_diagnostic.IDE0032.severity = silent # https://github.com/dotnet/extensions/issues/6864 tracks re-enabling this +dotnet_diagnostic.IDE0032.severity = warning dotnet_style_prefer_auto_properties = true # Title : Use explicitly provided tuple name @@ -5889,7 +5889,7 @@ dotnet_diagnostic.SA1414.severity = warning # Title : Braces for multi-line statements should not share line # Category : StyleCop.CSharp.LayoutRules # Help Link: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1500.md -dotnet_diagnostic.SA1500.severity = warning +dotnet_diagnostic.SA1500.severity = suggestion # rule does not work well with field-based property initializers # Title : Statement should not be on a single line # Category : StyleCop.CSharp.LayoutRules @@ -5957,7 +5957,7 @@ dotnet_diagnostic.SA1512.severity = none # Title : Closing brace should be followed by blank line # Category : StyleCop.CSharp.LayoutRules # Help Link: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1513.md -dotnet_diagnostic.SA1513.severity = warning +dotnet_diagnostic.SA1513.severity = suggestion # rule does not work well with field-based property initializers # Title : Element documentation header should be preceded by blank line # Category : StyleCop.CSharp.LayoutRules diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatFinishReason.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatFinishReason.cs index 18b3ec658e3..1852aa07f7c 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatFinishReason.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatFinishReason.cs @@ -14,9 +14,6 @@ namespace Microsoft.Extensions.AI; [JsonConverter(typeof(Converter))] public readonly struct ChatFinishReason : IEquatable { - /// The finish reason value. If because `default(ChatFinishReason)` was used, the instance will behave like . - private readonly string? _value; - /// Initializes a new instance of the struct with a string that describes the reason. /// The reason value. /// is . @@ -24,11 +21,11 @@ namespace Microsoft.Extensions.AI; [JsonConstructor] public ChatFinishReason(string value) { - _value = Throw.IfNullOrWhitespace(value); + Value = Throw.IfNullOrWhitespace(value); } /// Gets the finish reason value. - public string Value => _value ?? Stop.Value; + public string Value => field ?? Stop.Value; /// public override bool Equals([NotNullWhen(true)] object? obj) => obj is ChatFinishReason other && Equals(other); diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseUpdate.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseUpdate.cs index 6a4f11c3777..0605d0785bb 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseUpdate.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseUpdate.cs @@ -35,9 +35,6 @@ public class ChatResponseUpdate /// The response update content items. private IList? _contents; - /// The name of the author of the update. - private string? _authorName; - /// Initializes a new instance of the class. [JsonConstructor] public ChatResponseUpdate() @@ -64,8 +61,8 @@ public ChatResponseUpdate(ChatRole? role, IList? contents) /// Gets or sets the name of the author of the response update. public string? AuthorName { - get => _authorName; - set => _authorName = string.IsNullOrWhiteSpace(value) ? null : value; + get; + set => field = string.IsNullOrWhiteSpace(value) ? null : value; } /// Gets or sets the role of the author of the response update. diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/DataContent.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/DataContent.cs index 4b8813c144e..7b2ef0ccb1a 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/DataContent.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/DataContent.cs @@ -15,6 +15,7 @@ using System.Text.Json.Serialization; using Microsoft.Shared.Diagnostics; +#pragma warning disable IDE0032 // Use auto property #pragma warning disable CA1307 // Specify StringComparison for clarity namespace Microsoft.Extensions.AI; diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ErrorContent.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ErrorContent.cs index 4588531262b..4b82c4c5e91 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ErrorContent.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ErrorContent.cs @@ -14,22 +14,19 @@ namespace Microsoft.Extensions.AI; [DebuggerDisplay("{DebuggerDisplay,nq}")] public class ErrorContent : AIContent { - /// The error message. - private string? _message; - /// Initializes a new instance of the class with the specified error message. /// The error message to store in this content. public ErrorContent(string? message) { - _message = message; + Message = message; } /// Gets or sets the error message. [AllowNull] public string Message { - get => _message ?? string.Empty; - set => _message = value; + get => field ?? string.Empty; + set; } /// Gets or sets an error code associated with the error. diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/TextContent.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/TextContent.cs index 0f70a5f8b0a..d6bac57420f 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/TextContent.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/TextContent.cs @@ -12,15 +12,13 @@ namespace Microsoft.Extensions.AI; [DebuggerDisplay("{DebuggerDisplay,nq}")] public sealed class TextContent : AIContent { - private string? _text; - /// /// Initializes a new instance of the class. /// /// The text content. public TextContent(string? text) { - _text = text; + Text = text; } /// @@ -29,8 +27,8 @@ public TextContent(string? text) [AllowNull] public string Text { - get => _text ?? string.Empty; - set => _text = value; + get => field ?? string.Empty; + set; } /// diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/TextReasoningContent.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/TextReasoningContent.cs index 345cb430dbd..57fec14cc0e 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/TextReasoningContent.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/TextReasoningContent.cs @@ -17,15 +17,13 @@ namespace Microsoft.Extensions.AI; [DebuggerDisplay("{DebuggerDisplay,nq}")] public sealed class TextReasoningContent : AIContent { - private string? _text; - /// /// Initializes a new instance of the class. /// /// The text reasoning content. public TextReasoningContent(string? text) { - _text = text; + Text = text; } /// @@ -34,8 +32,8 @@ public TextReasoningContent(string? text) [AllowNull] public string Text { - get => _text ?? string.Empty; - set => _text = value; + get => field ?? string.Empty; + set; } /// Gets or sets an optional opaque blob of data associated with this reasoning content. diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Embeddings/EmbeddingGenerationOptions.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Embeddings/EmbeddingGenerationOptions.cs index b9a13d43dd0..4d88c85b760 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Embeddings/EmbeddingGenerationOptions.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Embeddings/EmbeddingGenerationOptions.cs @@ -10,12 +10,10 @@ namespace Microsoft.Extensions.AI; /// Represents the options for an embedding generation request. public class EmbeddingGenerationOptions { - private int? _dimensions; - /// Gets or sets the number of dimensions requested in the embedding. public int? Dimensions { - get => _dimensions; + get; set { if (value is not null) @@ -23,7 +21,7 @@ public int? Dimensions _ = Throw.IfLessThan(value.Value, 1, nameof(value)); } - _dimensions = value; + field = value; } } diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Image/ImageGenerationResponse.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Image/ImageGenerationResponse.cs index ba3abe8f1a3..8f093634783 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Image/ImageGenerationResponse.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Image/ImageGenerationResponse.cs @@ -11,9 +11,6 @@ namespace Microsoft.Extensions.AI; [Experimental("MEAI001")] public class ImageGenerationResponse { - /// The content items in the generated text response. - private IList? _contents; - /// Initializes a new instance of the class. [JsonConstructor] public ImageGenerationResponse() @@ -24,7 +21,7 @@ public ImageGenerationResponse() /// The contents for this response. public ImageGenerationResponse(IList? contents) { - _contents = contents; + Contents = contents; } /// Gets or sets the raw representation of the image generation response from an underlying implementation. @@ -46,8 +43,8 @@ public ImageGenerationResponse(IList? contents) [AllowNull] public IList Contents { - get => _contents ??= []; - set => _contents = value; + get => field ??= []; + set; } /// Gets or sets usage details for the image generation response. diff --git a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting.Azure/JsonSerialization/AzureStorageJsonUtilities.cs b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting.Azure/JsonSerialization/AzureStorageJsonUtilities.cs index 204ac68394b..c2f7b418b01 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting.Azure/JsonSerialization/AzureStorageJsonUtilities.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting.Azure/JsonSerialization/AzureStorageJsonUtilities.cs @@ -13,16 +13,14 @@ internal static partial class AzureStorageJsonUtilities { internal static class Default { - private static JsonSerializerOptions? _options; - internal static JsonSerializerOptions Options => _options ??= CreateJsonSerializerOptions(writeIndented: true); + internal static JsonSerializerOptions Options => field ??= CreateJsonSerializerOptions(writeIndented: true); internal static JsonTypeInfo CacheEntryTypeInfo => Options.GetTypeInfo(); internal static JsonTypeInfo ScenarioRunResultTypeInfo => Options.GetTypeInfo(); } internal static class Compact { - private static JsonSerializerOptions? _options; - internal static JsonSerializerOptions Options => _options ??= CreateJsonSerializerOptions(writeIndented: false); + internal static JsonSerializerOptions Options => field ??= CreateJsonSerializerOptions(writeIndented: false); internal static JsonTypeInfo CacheEntryTypeInfo => Options.GetTypeInfo(); internal static JsonTypeInfo ScenarioRunResultTypeInfo => Options.GetTypeInfo(); } diff --git a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting/CSharp/JsonSerialization/JsonUtilities.cs b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting/CSharp/JsonSerialization/JsonUtilities.cs index fb514bd33c8..9427b67be8e 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting/CSharp/JsonSerialization/JsonUtilities.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting/CSharp/JsonSerialization/JsonUtilities.cs @@ -14,8 +14,7 @@ internal static partial class JsonUtilities { internal static class Default { - private static JsonSerializerOptions? _options; - internal static JsonSerializerOptions Options => _options ??= CreateJsonSerializerOptions(writeIndented: true); + internal static JsonSerializerOptions Options => field ??= CreateJsonSerializerOptions(writeIndented: true); internal static JsonTypeInfo DatasetTypeInfo => Options.GetTypeInfo(); internal static JsonTypeInfo CacheEntryTypeInfo => Options.GetTypeInfo(); internal static JsonTypeInfo ScenarioRunResultTypeInfo => Options.GetTypeInfo(); @@ -23,8 +22,7 @@ internal static class Default internal static class Compact { - private static JsonSerializerOptions? _options; - internal static JsonSerializerOptions Options => _options ??= CreateJsonSerializerOptions(writeIndented: false); + internal static JsonSerializerOptions Options => field ??= CreateJsonSerializerOptions(writeIndented: false); internal static JsonTypeInfo DatasetTypeInfo => Options.GetTypeInfo(); internal static JsonTypeInfo CacheEntryTypeInfo => Options.GetTypeInfo(); internal static JsonTypeInfo ScenarioRunResultTypeInfo => Options.GetTypeInfo(); diff --git a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Safety/ContentSafetyService.cs b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Safety/ContentSafetyService.cs index 18d9f52d2c4..26dec553915 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Safety/ContentSafetyService.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Safety/ContentSafetyService.cs @@ -20,15 +20,10 @@ internal sealed partial class ContentSafetyService(ContentSafetyServiceConfigura private const string APIVersionForServiceDiscoveryInHubBasedProjects = "?api-version=2023-08-01-preview"; private const string APIVersionForNonHubBasedProjects = "?api-version=2025-05-15-preview"; - private static HttpClient? _sharedHttpClient; - private static HttpClient SharedHttpClient - { - get - { - _sharedHttpClient ??= new HttpClient(); - return _sharedHttpClient; - } - } + private static HttpClient SharedHttpClient => + field ?? + Interlocked.CompareExchange(ref field, new(), null) ?? + field; private static readonly ConcurrentDictionary _serviceUrlCache = new ConcurrentDictionary(); diff --git a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/DistributedCachingChatClient.cs b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/DistributedCachingChatClient.cs index 47984962598..44ddcf84081 100644 --- a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/DistributedCachingChatClient.cs +++ b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/DistributedCachingChatClient.cs @@ -44,9 +44,6 @@ public class DistributedCachingChatClient : CachingChatClient /// Additional values used to inform the cache key employed for storing state. private object[]? _cacheKeyAdditionalValues; - /// The to use when serializing cache data. - private JsonSerializerOptions _jsonSerializerOptions = AIJsonUtilities.DefaultOptions; - /// Initializes a new instance of the class. /// The underlying . /// An instance that will be used as the backing store for the cache. @@ -59,9 +56,9 @@ public DistributedCachingChatClient(IChatClient innerClient, IDistributedCache s /// Gets or sets JSON serialization options to use when serializing cache data. public JsonSerializerOptions JsonSerializerOptions { - get => _jsonSerializerOptions; - set => _jsonSerializerOptions = Throw.IfNull(value); - } + get; + set => field = Throw.IfNull(value); + } = AIJsonUtilities.DefaultOptions; /// Gets or sets additional values used to inform the cache key employed for storing state. /// Any values set in this list will augment the other values used to inform the cache key. @@ -75,11 +72,11 @@ public IReadOnlyList? CacheKeyAdditionalValues protected override async Task ReadCacheAsync(string key, CancellationToken cancellationToken) { _ = Throw.IfNull(key); - _jsonSerializerOptions.MakeReadOnly(); + JsonSerializerOptions.MakeReadOnly(); if (await _storage.GetAsync(key, cancellationToken) is byte[] existingJson) { - return (ChatResponse?)JsonSerializer.Deserialize(existingJson, _jsonSerializerOptions.GetTypeInfo(typeof(ChatResponse))); + return (ChatResponse?)JsonSerializer.Deserialize(existingJson, JsonSerializerOptions.GetTypeInfo(typeof(ChatResponse))); } return null; @@ -89,11 +86,11 @@ public IReadOnlyList? CacheKeyAdditionalValues protected override async Task?> ReadCacheStreamingAsync(string key, CancellationToken cancellationToken) { _ = Throw.IfNull(key); - _jsonSerializerOptions.MakeReadOnly(); + JsonSerializerOptions.MakeReadOnly(); if (await _storage.GetAsync(key, cancellationToken) is byte[] existingJson) { - return (IReadOnlyList?)JsonSerializer.Deserialize(existingJson, _jsonSerializerOptions.GetTypeInfo(typeof(IReadOnlyList))); + return (IReadOnlyList?)JsonSerializer.Deserialize(existingJson, JsonSerializerOptions.GetTypeInfo(typeof(IReadOnlyList))); } return null; @@ -104,9 +101,9 @@ protected override async Task WriteCacheAsync(string key, ChatResponse value, Ca { _ = Throw.IfNull(key); _ = Throw.IfNull(value); - _jsonSerializerOptions.MakeReadOnly(); + JsonSerializerOptions.MakeReadOnly(); - var newJson = JsonSerializer.SerializeToUtf8Bytes(value, _jsonSerializerOptions.GetTypeInfo(typeof(ChatResponse))); + var newJson = JsonSerializer.SerializeToUtf8Bytes(value, JsonSerializerOptions.GetTypeInfo(typeof(ChatResponse))); await _storage.SetAsync(key, newJson, cancellationToken); } @@ -115,9 +112,9 @@ protected override async Task WriteCacheStreamingAsync(string key, IReadOnlyList { _ = Throw.IfNull(key); _ = Throw.IfNull(value); - _jsonSerializerOptions.MakeReadOnly(); + JsonSerializerOptions.MakeReadOnly(); - var newJson = JsonSerializer.SerializeToUtf8Bytes(value, _jsonSerializerOptions.GetTypeInfo(typeof(IReadOnlyList))); + var newJson = JsonSerializer.SerializeToUtf8Bytes(value, JsonSerializerOptions.GetTypeInfo(typeof(IReadOnlyList))); await _storage.SetAsync(key, newJson, cancellationToken); } @@ -151,7 +148,7 @@ protected override string GetCacheKey(IEnumerable messages, ChatOpt additionalValues.CopyTo(arr.AsSpan(FixedValuesCount)); clientValues.CopyTo(arr, FixedValuesCount + additionalValues.Length); - return AIJsonUtilities.HashDataToString(arr.AsSpan(0, length), _jsonSerializerOptions); + return AIJsonUtilities.HashDataToString(arr.AsSpan(0, length), JsonSerializerOptions); } finally { diff --git a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvocationContext.cs b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvocationContext.cs index 0e426615cfd..554918b0a8e 100644 --- a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvocationContext.cs +++ b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvocationContext.cs @@ -17,18 +17,6 @@ public class FunctionInvocationContext /// private static readonly AIFunction _nopFunction = AIFunctionFactory.Create(() => { }, nameof(FunctionInvocationContext)); - /// The chat contents associated with the operation that initiated this function call request. - private IList _messages = Array.Empty(); - - /// The AI function to be invoked. - private AIFunction _function = _nopFunction; - - /// The function call content information associated with this invocation. - private FunctionCallContent? _callContent; - - /// The arguments used with the function. - private AIFunctionArguments? _arguments; - /// Initializes a new instance of the class. public FunctionInvocationContext() { @@ -37,30 +25,30 @@ public FunctionInvocationContext() /// Gets or sets the AI function to be invoked. public AIFunction Function { - get => _function; - set => _function = Throw.IfNull(value); - } + get; + set => field = Throw.IfNull(value); + } = _nopFunction; /// Gets or sets the arguments associated with this invocation. public AIFunctionArguments Arguments { - get => _arguments ??= []; - set => _arguments = Throw.IfNull(value); + get => field ??= []; + set => field = Throw.IfNull(value); } /// Gets or sets the function call content information associated with this invocation. public FunctionCallContent CallContent { - get => _callContent ??= new(string.Empty, _nopFunction.Name, EmptyReadOnlyDictionary.Instance); - set => _callContent = Throw.IfNull(value); + get => field ??= new(string.Empty, _nopFunction.Name, EmptyReadOnlyDictionary.Instance); + set => field = Throw.IfNull(value); } /// Gets or sets the chat contents associated with the operation that initiated this function call request. public IList Messages { - get => _messages; - set => _messages = Throw.IfNull(value); - } + get; + set => field = Throw.IfNull(value); + } = Array.Empty(); /// Gets or sets the chat options associated with the operation that initiated this function call request. public ChatOptions? Options { get; set; } diff --git a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs index 4495d592adb..fdc5ef7a204 100644 --- a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs +++ b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs @@ -16,8 +16,6 @@ #pragma warning disable CA2213 // Disposable fields should be disposed #pragma warning disable S3353 // Unchanged local variables should be "const" -#pragma warning disable IDE0031 // Use null propagation, suppressed until repo updates to C# 14 -#pragma warning disable IDE0032 // Use auto property, suppressed until repo updates to C# 14 namespace Microsoft.Extensions.AI; @@ -79,12 +77,6 @@ public partial class FunctionInvokingChatClient : DelegatingChatClient /// This component does not own the instance and should not dispose it. private readonly ActivitySource? _activitySource; - /// Maximum number of roundtrips allowed to the inner client. - private int _maximumIterationsPerRequest = 40; // arbitrary default to prevent runaway execution - - /// Maximum number of consecutive iterations that are allowed contain at least one exception result. If the limit is exceeded, we rethrow the exception instead of continuing. - private int _maximumConsecutiveErrorsPerRequest = 3; - /// /// Initializes a new instance of the class. /// @@ -178,7 +170,7 @@ public static FunctionInvocationContext? CurrentContext /// public int MaximumIterationsPerRequest { - get => _maximumIterationsPerRequest; + get; set { if (value < 1) @@ -186,9 +178,9 @@ public int MaximumIterationsPerRequest Throw.ArgumentOutOfRangeException(nameof(value)); } - _maximumIterationsPerRequest = value; + field = value; } - } + } = 40; /// /// Gets or sets the maximum number of consecutive iterations that are allowed to fail with an error. @@ -220,9 +212,9 @@ public int MaximumIterationsPerRequest /// public int MaximumConsecutiveErrorsPerRequest { - get => _maximumConsecutiveErrorsPerRequest; - set => _maximumConsecutiveErrorsPerRequest = Throw.IfLessThan(value, 0); - } + get; + set => field = Throw.IfLessThan(value, 0); + } = 3; /// Gets or sets a collection of additional tools the client is able to invoke. /// @@ -1430,10 +1422,9 @@ private static (List? approvals, List cm) diff --git a/src/Libraries/Microsoft.Extensions.AI/ChatReduction/SummarizingChatReducer.cs b/src/Libraries/Microsoft.Extensions.AI/ChatReduction/SummarizingChatReducer.cs index b79d1d18197..f097c1c9a35 100644 --- a/src/Libraries/Microsoft.Extensions.AI/ChatReduction/SummarizingChatReducer.cs +++ b/src/Libraries/Microsoft.Extensions.AI/ChatReduction/SummarizingChatReducer.cs @@ -45,16 +45,14 @@ public sealed class SummarizingChatReducer : IChatReducer private readonly int _targetCount; private readonly int _thresholdCount; - private string _summarizationPrompt = DefaultSummarizationPrompt; - /// /// Gets or sets the prompt text used for summarization. /// public string SummarizationPrompt { - get => _summarizationPrompt; - set => _summarizationPrompt = Throw.IfNull(value); - } + get; + set => field = Throw.IfNull(value); + } = DefaultSummarizationPrompt; /// /// Initializes a new instance of the class with the specified chat client, @@ -79,7 +77,7 @@ public async Task> ReduceAsync(IEnumerable if (summarizedConversion.ShouldResummarize(_targetCount, _thresholdCount)) { summarizedConversion = await summarizedConversion.ResummarizeAsync( - _chatClient, _targetCount, _summarizationPrompt, cancellationToken); + _chatClient, _targetCount, SummarizationPrompt, cancellationToken); } return summarizedConversion.ToChatMessages(); diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/ManualHealthCheck.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/ManualHealthCheck.cs index 0302b1a896f..d9faa46f338 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/ManualHealthCheck.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/ManualHealthCheck.cs @@ -10,22 +10,20 @@ internal sealed class ManualHealthCheck : IManualHealthCheck { private static readonly object _lock = new(); - private HealthCheckResult _result; - public HealthCheckResult Result { get { lock (_lock) { - return _result; + return field; } } set { lock (_lock) { - _result = value; + field = value; } } } diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Polly/HttpRetryStrategyOptions.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Polly/HttpRetryStrategyOptions.cs index db0a8850e20..7f105586ea6 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/Polly/HttpRetryStrategyOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Polly/HttpRetryStrategyOptions.cs @@ -16,8 +16,6 @@ namespace Microsoft.Extensions.Http.Resilience; /// public class HttpRetryStrategyOptions : RetryStrategyOptions { - private bool _shouldRetryAfterHeader; - /// /// Initializes a new instance of the class. /// @@ -47,12 +45,12 @@ public HttpRetryStrategyOptions() /// public bool ShouldRetryAfterHeader { - get => _shouldRetryAfterHeader; + get; set { - _shouldRetryAfterHeader = value; + field = value; - if (_shouldRetryAfterHeader) + if (field) { DelayGenerator = args => args.Outcome.Result switch { diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/UriEndpoint.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/UriEndpoint.cs index 2373144556d..028eaca7762 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/UriEndpoint.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/UriEndpoint.cs @@ -6,15 +6,11 @@ namespace Microsoft.Extensions.Http.Resilience; -#pragma warning disable IDE0032 // Use auto property - /// /// Represents a URI-based endpoint. /// public class UriEndpoint { - private Uri? _uri; - /// /// Gets or sets the URL of the endpoint. /// @@ -22,9 +18,5 @@ public class UriEndpoint /// Only schema, domain name, and port are used. The rest of the URL is constructed from the request URL. /// [Required] - public Uri? Uri - { - get => _uri; - set => _uri = value; - } + public Uri? Uri { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Logging/LoggerMessageHelper.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Logging/LoggerMessageHelper.cs index bb3631909dc..34d9df008ad 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Logging/LoggerMessageHelper.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Logging/LoggerMessageHelper.cs @@ -18,26 +18,11 @@ namespace Microsoft.Extensions.Logging; [EditorBrowsable(EditorBrowsableState.Never)] public static class LoggerMessageHelper { - [ThreadStatic] - private static LoggerMessageState? _state; - /// /// Gets a thread-local instance of this type. /// - public static LoggerMessageState ThreadLocalState - { - get - { - var result = _state; - if (result == null) - { - result = new(); - _state = result; - } - - return result; - } - } + [field: ThreadStatic] + public static LoggerMessageState ThreadLocalState => field ??= new(); /// /// Enumerates an enumerable into a string. diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Latency/Internal/CheckpointTracker.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Latency/Internal/CheckpointTracker.cs index ba2c1646760..5cee914c68a 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Latency/Internal/CheckpointTracker.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Latency/Internal/CheckpointTracker.cs @@ -16,12 +16,13 @@ internal sealed class CheckpointTracker : IResettable private readonly Registry _checkpointNames; private readonly int[] _checkpointAdded; private readonly Checkpoint[] _checkpoints; - - private long _timestamp; - private int _numCheckpoints; - public long Elapsed => TimeProvider.GetTimestamp() - _timestamp; + public long Elapsed + { + get => TimeProvider.GetTimestamp() - field; + private set; + } public long Frequency => TimeProvider.TimestampFrequency; @@ -36,7 +37,7 @@ public CheckpointTracker(Registry registry) _checkpointAdded = new int[keyCount]; _checkpoints = new Checkpoint[keyCount]; TimeProvider = TimeProvider.System; - _timestamp = TimeProvider.GetTimestamp(); + Elapsed = TimeProvider.GetTimestamp(); } /// @@ -44,7 +45,7 @@ public CheckpointTracker(Registry registry) /// public bool TryReset() { - _timestamp = TimeProvider.GetTimestamp(); + Elapsed = TimeProvider.GetTimestamp(); _numCheckpoints = 0; Array.Clear(_checkpointAdded, 0, _checkpointAdded.Length); return true; diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Latency/Internal/LatencyContext.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Latency/Internal/LatencyContext.cs index 0777d03c571..251d7cedc1c 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Latency/Internal/LatencyContext.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Latency/Internal/LatencyContext.cs @@ -22,8 +22,6 @@ internal sealed class LatencyContext : ILatencyContext, IResettable private readonly MeasureTracker _measureTracker; - private long _duration; - public LatencyContext(LatencyContextPool latencyContextPool) { var latencyInstrumentProvider = latencyContextPool.LatencyInstrumentProvider; @@ -36,7 +34,11 @@ public LatencyContext(LatencyContextPool latencyContextPool) public LatencyData LatencyData => IsDisposed ? default : new(_tagCollection.Tags, _checkpointTracker.Checkpoints, _measureTracker.Measures, Duration, _checkpointTracker.Frequency); - private long Duration => IsRunning ? _checkpointTracker.Elapsed : _duration; + private long Duration + { + get => IsRunning ? _checkpointTracker.Elapsed : field; + set; + } #region Checkpoints public void AddCheckpoint(CheckpointToken token) @@ -82,7 +84,7 @@ public void Freeze() if (IsRunning) { IsRunning = false; - _duration = _checkpointTracker.Elapsed; + Duration = _checkpointTracker.Elapsed; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Logging/ExtendedLogger.LegacyTagJoiner.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Logging/ExtendedLogger.LegacyTagJoiner.cs index 46bf77f0816..3f75af17a34 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Logging/ExtendedLogger.LegacyTagJoiner.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Logging/ExtendedLogger.LegacyTagJoiner.cs @@ -21,7 +21,6 @@ internal sealed class LegacyTagJoiner : IReadOnlyList> _extraTags = new(TagCapacity); private IReadOnlyList>? _incomingTags; - private int _incomingTagCount; public LegacyTagJoiner() { @@ -34,7 +33,7 @@ public void Clear() { _extraTags.Clear(); _incomingTags = null; - _incomingTagCount = 0; + Count = 0; State = null; Formatter = null; } @@ -43,7 +42,7 @@ public void Clear() public void SetIncomingTags(IReadOnlyList> value) { _incomingTags = value; - _incomingTagCount = _incomingTags.Count; + Count = _incomingTags.Count; } public KeyValuePair this[int index] @@ -77,7 +76,11 @@ public void SetIncomingTags(IReadOnlyList> value) } } - public int Count => _incomingTagCount + _extraTags.Count + StaticTags!.Length; + public int Count + { + get => field + _extraTags.Count + StaticTags!.Length; + private set; + } public IEnumerator> GetEnumerator() { diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Logging/ExtendedLogger.ThreadLocals.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Logging/ExtendedLogger.ThreadLocals.cs index 77e1ddc1fd1..21cf296e62c 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Logging/ExtendedLogger.ThreadLocals.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Logging/ExtendedLogger.ThreadLocals.cs @@ -5,43 +5,11 @@ namespace Microsoft.Extensions.Logging; -#pragma warning disable S2696 - internal sealed partial class ExtendedLogger : ILogger { - [ThreadStatic] - private static ModernTagJoiner? _modernJoiner; - - [ThreadStatic] - private static LegacyTagJoiner? _legacyJoiner; - - private static ModernTagJoiner ModernJoiner - { - get - { - var joiner = _modernJoiner; - if (joiner == null) - { - joiner = new(); - _modernJoiner = joiner; - } - - return joiner; - } - } - - private static LegacyTagJoiner LegacyJoiner - { - get - { - var joiner = _legacyJoiner; - if (joiner == null) - { - joiner = new(); - _legacyJoiner = joiner; - } + [field: ThreadStatic] + private static ModernTagJoiner ModernJoiner => field ??= new(); - return joiner; - } - } + [field: ThreadStatic] + private static LegacyTagJoiner LegacyJoiner => field ??= new(); } diff --git a/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/FakeTimeProvider.cs b/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/FakeTimeProvider.cs index b9404afa30e..cfe601e9dfa 100644 --- a/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/FakeTimeProvider.cs +++ b/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/FakeTimeProvider.cs @@ -19,7 +19,6 @@ public class FakeTimeProvider : TimeProvider private DateTimeOffset _now = new(2000, 1, 1, 0, 0, 0, 0, TimeSpan.Zero); private TimeZoneInfo _localTimeZone = TimeZoneInfo.Utc; private volatile int _wakeWaitersGate; - private TimeSpan _autoAdvanceAmount; /// /// Initializes a new instance of the class. @@ -62,11 +61,11 @@ public FakeTimeProvider(DateTimeOffset startDateTime) /// The time value is less than . public TimeSpan AutoAdvanceAmount { - get => _autoAdvanceAmount; + get; set { _ = Throw.IfLessThan(value.Ticks, 0); - _autoAdvanceAmount = value; + field = value; } } @@ -78,7 +77,7 @@ public override DateTimeOffset GetUtcNow() lock (Waiters) { result = _now; - _now += _autoAdvanceAmount; + _now += AutoAdvanceAmount; } WakeWaiters(); diff --git a/src/Shared/.editorconfig b/src/Shared/.editorconfig index 59e9e2090d9..defd1d59afc 100644 --- a/src/Shared/.editorconfig +++ b/src/Shared/.editorconfig @@ -1991,7 +1991,7 @@ dotnet_style_null_propagation = true # Title : Use auto property # Category : Style # Help Link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0032 -dotnet_diagnostic.IDE0032.severity = silent # https://github.com/dotnet/extensions/issues/6864 tracks re-enabling this +dotnet_diagnostic.IDE0032.severity = warning dotnet_style_prefer_auto_properties = true # Title : Use explicitly provided tuple name @@ -5868,7 +5868,7 @@ dotnet_diagnostic.SA1414.severity = warning # Title : Braces for multi-line statements should not share line # Category : StyleCop.CSharp.LayoutRules # Help Link: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1500.md -dotnet_diagnostic.SA1500.severity = warning +dotnet_diagnostic.SA1500.severity = suggestion # rule does not work well with field-based property initializers # Title : Statement should not be on a single line # Category : StyleCop.CSharp.LayoutRules @@ -5936,7 +5936,7 @@ dotnet_diagnostic.SA1512.severity = none # Title : Closing brace should be followed by blank line # Category : StyleCop.CSharp.LayoutRules # Help Link: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1513.md -dotnet_diagnostic.SA1513.severity = warning +dotnet_diagnostic.SA1513.severity = suggestion # rule does not work well with field-based property initializers # Title : Element documentation header should be preceded by blank line # Category : StyleCop.CSharp.LayoutRules diff --git a/src/Shared/JsonSchemaExporter/JsonSchemaExporter.JsonSchema.cs b/src/Shared/JsonSchemaExporter/JsonSchemaExporter.JsonSchema.cs index a395c133980..5380d208259 100644 --- a/src/Shared/JsonSchemaExporter/JsonSchemaExporter.JsonSchema.cs +++ b/src/Shared/JsonSchemaExporter/JsonSchemaExporter.JsonSchema.cs @@ -35,244 +35,204 @@ private JsonSchema(bool trueOrFalse) public string? Schema { - get => _schema; + get; set { VerifyMutable(); - _schema = value; + field = value; } } - private string? _schema; - public string? Title { - get => _title; + get; set { VerifyMutable(); - _title = value; + field = value; } } - private string? _title; - public string? Description { - get => _description; + get; set { VerifyMutable(); - _description = value; + field = value; } } - private string? _description; - public string? Ref { - get => _ref; + get; set { VerifyMutable(); - _ref = value; + field = value; } } - private string? _ref; - public string? Comment { - get => _comment; + get; set { VerifyMutable(); - _comment = value; + field = value; } } - private string? _comment; - public JsonSchemaType Type { - get => _type; + get; set { VerifyMutable(); - _type = value; + field = value; } - } - - private JsonSchemaType _type = JsonSchemaType.Any; + } = JsonSchemaType.Any; public string? Format { - get => _format; + get; set { VerifyMutable(); - _format = value; + field = value; } } - private string? _format; - public string? Pattern { - get => _pattern; + get; set { VerifyMutable(); - _pattern = value; + field = value; } } - private string? _pattern; - public JsonNode? Constant { - get => _constant; + get; set { VerifyMutable(); - _constant = value; + field = value; } } - private JsonNode? _constant; - public List>? Properties { - get => _properties; + get; set { VerifyMutable(); - _properties = value; + field = value; } } - private List>? _properties; - public List? Required { - get => _required; + get; set { VerifyMutable(); - _required = value; + field = value; } } - private List? _required; - public JsonSchema? Items { - get => _items; + get; set { VerifyMutable(); - _items = value; + field = value; } } - private JsonSchema? _items; - public JsonSchema? AdditionalProperties { - get => _additionalProperties; + get; set { VerifyMutable(); - _additionalProperties = value; + field = value; } } - private JsonSchema? _additionalProperties; - public JsonArray? Enum { - get => _enum; + get; set { VerifyMutable(); - _enum = value; + field = value; } } - private JsonArray? _enum; - public JsonSchema? Not { - get => _not; + get; set { VerifyMutable(); - _not = value; + field = value; } } - private JsonSchema? _not; - public List? AnyOf { - get => _anyOf; + get; set { VerifyMutable(); - _anyOf = value; + field = value; } } - private List? _anyOf; - public bool HasDefaultValue { - get => _hasDefaultValue; + get; set { VerifyMutable(); - _hasDefaultValue = value; + field = value; } } - private bool _hasDefaultValue; - public JsonNode? DefaultValue { - get => _defaultValue; + get; set { VerifyMutable(); - _defaultValue = value; + field = value; } } - private JsonNode? _defaultValue; - public int? MinLength { - get => _minLength; + get; set { VerifyMutable(); - _minLength = value; + field = value; } } - private int? _minLength; - public int? MaxLength { - get => _maxLength; + get; set { VerifyMutable(); - _maxLength = value; + field = value; } } - private int? _maxLength; - public JsonSchemaExporterContext? GenerationContext { get; set; } public int KeywordCount diff --git a/src/Shared/ServerSentEvents/SseItem.cs b/src/Shared/ServerSentEvents/SseItem.cs index 9c6092fd3cf..013d2fe9098 100644 --- a/src/Shared/ServerSentEvents/SseItem.cs +++ b/src/Shared/ServerSentEvents/SseItem.cs @@ -17,12 +17,6 @@ internal readonly struct SseItem [EditorBrowsable(EditorBrowsableState.Never)] internal readonly string? _eventType; - /// The event's id. - private readonly string? _eventId; - - /// The event's reconnection interval. - private readonly TimeSpan? _reconnectionInterval; - /// Initializes a new instance of the struct. /// The event's payload. /// The event's type. @@ -48,7 +42,7 @@ public SseItem(T data, string? eventType = null) /// Thrown when the value contains a line break. public string? EventId { - get => _eventId; + get; init { if (value.AsSpan().ContainsLineBreaks() is true) @@ -56,7 +50,7 @@ public string? EventId ThrowHelper.ThrowArgumentException_CannotContainLineBreaks(nameof(EventId)); } - _eventId = value; + field = value; } } @@ -66,7 +60,7 @@ public string? EventId /// public TimeSpan? ReconnectionInterval { - get => _reconnectionInterval; + get; init { if (value < TimeSpan.Zero) @@ -74,7 +68,7 @@ public TimeSpan? ReconnectionInterval ThrowHelper.ThrowArgumentException_CannotBeNegative(nameof(ReconnectionInterval)); } - _reconnectionInterval = value; + field = value; } } } diff --git a/test/.editorconfig b/test/.editorconfig index ca9523939db..e98d1472b6a 100644 --- a/test/.editorconfig +++ b/test/.editorconfig @@ -1981,7 +1981,7 @@ dotnet_style_null_propagation = true # Title : Use auto property # Category : Style # Help Link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0032 -dotnet_diagnostic.IDE0032.severity = silent # https://github.com/dotnet/extensions/issues/6864 tracks re-enabling this +dotnet_diagnostic.IDE0032.severity = warning dotnet_style_prefer_auto_properties = true # Title : Use explicitly provided tuple name diff --git a/test/Libraries/Microsoft.AspNetCore.HeaderParsing.Tests/HeaderParsingFeatureTests.cs b/test/Libraries/Microsoft.AspNetCore.HeaderParsing.Tests/HeaderParsingFeatureTests.cs index 7bc5ddc95f2..15000ccb21a 100644 --- a/test/Libraries/Microsoft.AspNetCore.HeaderParsing.Tests/HeaderParsingFeatureTests.cs +++ b/test/Libraries/Microsoft.AspNetCore.HeaderParsing.Tests/HeaderParsingFeatureTests.cs @@ -23,13 +23,10 @@ public sealed class HeaderParsingFeatureTests private readonly IOptions _options; private readonly IServiceCollection _services; private readonly FakeLogger _logger = new(); - private IHeaderRegistry? _registry; - private HttpContext? _context; - private IHeaderRegistry Registry => _registry ??= new HeaderRegistry(_services.BuildServiceProvider(), _options); + private IHeaderRegistry Registry => field ??= new HeaderRegistry(_services.BuildServiceProvider(), _options); - private HttpContext Context - => _context ??= new DefaultHttpContext { RequestServices = _services.BuildServiceProvider() }; + private HttpContext Context => field ??= new DefaultHttpContext { RequestServices = _services.BuildServiceProvider() }; public HeaderParsingFeatureTests() { diff --git a/test/Libraries/Microsoft.Extensions.AI.Evaluation.Integration.Tests/Settings.cs b/test/Libraries/Microsoft.Extensions.AI.Evaluation.Integration.Tests/Settings.cs index 25ee9d544cb..7be73a05c10 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Evaluation.Integration.Tests/Settings.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Evaluation.Integration.Tests/Settings.cs @@ -57,16 +57,7 @@ public Settings(IConfiguration config) #pragma warning restore CA2208 } - private static Settings? _currentSettings; - - public static Settings Current - { - get - { - _currentSettings ??= GetCurrentSettings(); - return _currentSettings; - } - } + public static Settings Current => field ??= GetCurrentSettings(); private static Settings GetCurrentSettings() { diff --git a/test/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting.Tests/Settings.cs b/test/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting.Tests/Settings.cs index 366e4549748..1118d7f6624 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting.Tests/Settings.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting.Tests/Settings.cs @@ -27,16 +27,7 @@ public Settings(IConfiguration config) #pragma warning restore CA2208 } - private static Settings? _currentSettings; - - public static Settings Current - { - get - { - _currentSettings ??= GetCurrentSettings(); - return _currentSettings; - } - } + public static Settings Current => field ??= GetCurrentSettings(); private static Settings GetCurrentSettings() { diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Infrastructure/Project.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Infrastructure/Project.cs index 38ced5b1867..317e81a661f 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Infrastructure/Project.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Infrastructure/Project.cs @@ -8,30 +8,31 @@ namespace Microsoft.Extensions.AI.Templates.Tests; public sealed class Project(string rootPath, string name) { - private string? _startupProjectRelativePath; - private string? _startupProjectFullPath; - public string RootPath => rootPath; public string Name => name; public string? StartupProjectRelativePath { - get => _startupProjectRelativePath; + get; set { if (value is null) { - _startupProjectRelativePath = null; - _startupProjectFullPath = null; + field = null; + StartupProjectFullPath = null!; } - else if (!string.Equals(value, _startupProjectRelativePath, StringComparison.Ordinal)) + else if (!string.Equals(value, field, StringComparison.Ordinal)) { - _startupProjectRelativePath = value; - _startupProjectFullPath = Path.Combine(rootPath, _startupProjectRelativePath); + field = value; + StartupProjectFullPath = Path.Combine(rootPath, field); } } } - public string StartupProjectFullPath => _startupProjectFullPath ?? rootPath; + public string StartupProjectFullPath + { + get => field ?? rootPath; + private set; + } } diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Infrastructure/TestCommandResult.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Infrastructure/TestCommandResult.cs index 09d09d50a1c..4b5e2dd2a28 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Infrastructure/TestCommandResult.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Infrastructure/TestCommandResult.cs @@ -7,12 +7,9 @@ namespace Microsoft.Extensions.AI.Templates.Tests; public sealed class TestCommandResult(StringBuilder standardOutputBuilder, StringBuilder standardErrorBuilder, int exitCode) { - private string? _standardOutput; - private string? _standardError; + public string StandardOutput => field ??= standardOutputBuilder.ToString(); - public string StandardOutput => _standardOutput ??= standardOutputBuilder.ToString(); - - public string StandardError => _standardError ??= standardErrorBuilder.ToString(); + public string StandardError => field ??= standardErrorBuilder.ToString(); public int ExitCode => exitCode; }