diff --git a/docs/fundamentals/code-analysis/quality-rules/ca1873.md b/docs/fundamentals/code-analysis/quality-rules/ca1873.md new file mode 100644 index 0000000000000..3124289584046 --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/ca1873.md @@ -0,0 +1,172 @@ +--- +title: "CA1873: Avoid potentially expensive logging (code analysis)" +description: "Learn about code analysis rule CA1873: Avoid potentially expensive logging" +ms.date: 10/27/2025 +ms.topic: reference +f1_keywords: + - CA1873 + - AvoidPotentiallyExpensiveCallWhenLoggingAnalyzer +helpviewer_keywords: + - CA1873 +dev_langs: + - CSharp + - VB +ai-usage: ai-generated +--- + +# CA1873: Avoid potentially expensive logging + +| Property | Value | +|-------------------------------------|----------------------------------------| +| **Rule ID** | CA1873 | +| **Title** | Avoid potentially expensive logging | +| **Category** | [Performance](performance-warnings.md) | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default in .NET 10** | As suggestion | + +## Cause + +In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for logging arguments. + +## Rule description + +When logging methods are called, their arguments are evaluated regardless of whether the logging level is enabled. This can result in expensive operations being executed even when the log message won't be written. For better performance, guard expensive logging calls with a check to or use the `LoggerMessage` pattern. + +## How to fix violations + +To fix a violation of this rule, use one of the following approaches: + +- Guard the logging call with a check to . +- Use the `LoggerMessage` pattern with . +- Ensure expensive operations aren't performed in logging arguments unless necessary. + +## Example + +The following code snippet shows violations of CA1873: + +```csharp +using Microsoft.Extensions.Logging; + +class Example +{ + private readonly ILogger _logger; + + public Example(ILogger logger) + { + _logger = logger; + } + + public void ProcessData(int[] data) + { + // Violation: expensive operation in logging argument. + _logger.LogDebug($"Processing {string.Join(", ", data)} items"); + + // Violation: object creation in logging argument. + _logger.LogTrace("Data: {Data}", new { Count = data.Length, Items = data }); + } +} +``` + +```vb +Imports Microsoft.Extensions.Logging + +Class Example + Private ReadOnly _logger As ILogger + + Public Sub New(logger As ILogger(Of Example)) + _logger = logger + End Sub + + Public Sub ProcessData(data As Integer()) + ' Violation: expensive operation in logging argument. + _logger.LogDebug($"Processing {String.Join(", ", data)} items") + + ' Violation: object creation in logging argument. + _logger.LogTrace("Data: {Data}", New With {.Count = data.Length, .Items = data}) + End Sub +End Class +``` + +The following code snippet fixes the violations: + +```csharp +using Microsoft.Extensions.Logging; + +class Example +{ + private readonly ILogger _logger; + + public Example(ILogger logger) + { + _logger = logger; + } + + public void ProcessData(int[] data) + { + // Fixed: guard with IsEnabled check. + if (_logger.IsEnabled(LogLevel.Debug)) + { + _logger.LogDebug($"Processing {string.Join(", ", data)} items"); + } + + // Fixed: guard with IsEnabled check. + if (_logger.IsEnabled(LogLevel.Trace)) + { + _logger.LogTrace("Data: {Data}", new { Count = data.Length, Items = data }); + } + } +} +``` + +```vb +Imports Microsoft.Extensions.Logging + +Class Example + Private ReadOnly _logger As ILogger + + Public Sub New(logger As ILogger(Of Example)) + _logger = logger + End Sub + + Public Sub ProcessData(data As Integer()) + ' Fixed: guard with IsEnabled check. + If _logger.IsEnabled(LogLevel.Debug) Then + _logger.LogDebug($"Processing {String.Join(", ", data)} items") + End If + + ' Fixed: guard with IsEnabled check. + If _logger.IsEnabled(LogLevel.Trace) Then + _logger.LogTrace("Data: {Data}", New With {.Count = data.Length, .Items = data}) + End If + End Sub +End Class +``` + +## When to suppress warnings + +It's safe to suppress a warning from this rule if performance isn't a concern or if the logging arguments don't involve expensive operations. + +## 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 CA1873 +// The code that's violating the rule is on this line. +#pragma warning restore CA1873 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_diagnostic.CA1873.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../suppress-warnings.md). + +## See also + +- [Performance rules](performance-warnings.md) +- [High-performance logging in .NET](../../../core/extensions/high-performance-logging.md) +- [Compile-time logging source generation](../../../core/extensions/logger-message-generator.md) diff --git a/docs/fundamentals/code-analysis/quality-rules/ca1874.md b/docs/fundamentals/code-analysis/quality-rules/ca1874.md new file mode 100644 index 0000000000000..263a0c1c01ffc --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/ca1874.md @@ -0,0 +1,122 @@ +--- +title: "CA1874: Use 'Regex.IsMatch' (code analysis)" +description: "Learn about code analysis rule CA1874: Use 'Regex.IsMatch'" +ms.date: 10/27/2025 +ms.topic: reference +f1_keywords: + - CA1874 + - UseRegexIsMatchAnalyzer +helpviewer_keywords: + - CA1874 +dev_langs: + - CSharp + - VB +ai-usage: ai-generated +--- + +# CA1874: Use 'Regex.IsMatch' + +| Property | Value | +|-------------------------------------|----------------------------------------| +| **Rule ID** | CA1874 | +| **Title** | Use `Regex.IsMatch` | +| **Category** | [Performance](performance-warnings.md) | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default in .NET 10** | As suggestion | + +## Cause + +The property of the result from is used to check if a pattern matches. + +## Rule description + + is simpler and faster than `Regex.Match(...).Success`. The `IsMatch` method is optimized for the case where you only need to know whether a match exists, rather than what the match is. Calling `Match()` and then checking does unnecessary work that can impact performance. + +## How to fix violations + +Replace calls to `Regex.Match(...).Success` with `Regex.IsMatch(...)`. + +A *code fix* that automatically performs this transformation is available. + +## Example + +The following code snippet shows a violation of CA1874: + +```csharp +using System.Text.RegularExpressions; + +class Example +{ + public bool IsValidEmail(string email) + { + // Violation + return Regex.Match(email, @"^[^@\s]+@[^@\s]+\.[^@\s]+$").Success; + } +} +``` + +```vb +Imports System.Text.RegularExpressions + +Class Example + Public Function IsValidEmail(email As String) As Boolean + ' Violation + Return Regex.Match(email, "^[^@\s]+@[^@\s]+\.[^@\s]+$").Success + End Function +End Class +``` + +The following code snippet fixes the violation: + +```csharp +using System.Text.RegularExpressions; + +class Example +{ + public bool IsValidEmail(string email) + { + // Fixed + return Regex.IsMatch(email, @"^[^@\s]+@[^@\s]+\.[^@\s]+$"); + } +} +``` + +```vb +Imports System.Text.RegularExpressions + +Class Example + Public Function IsValidEmail(email As String) As Boolean + ' Fixed + Return Regex.IsMatch(email, "^[^@\s]+@[^@\s]+\.[^@\s]+$") + End Function +End Class +``` + +## When to suppress warnings + +It's safe to suppress a warning from this rule if performance isn't a concern. + +## 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 CA1874 +// The code that's violating the rule is on this line. +#pragma warning restore CA1874 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_diagnostic.CA1874.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../suppress-warnings.md). + +## See also + +- [Performance rules](performance-warnings.md) +- +- diff --git a/docs/fundamentals/code-analysis/quality-rules/ca1875.md b/docs/fundamentals/code-analysis/quality-rules/ca1875.md new file mode 100644 index 0000000000000..6d3aa8f30b30e --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/ca1875.md @@ -0,0 +1,122 @@ +--- +title: "CA1875: Use 'Regex.Count' (code analysis)" +description: "Learn about code analysis rule CA1875: Use 'Regex.Count'" +ms.date: 10/27/2025 +ms.topic: reference +f1_keywords: + - CA1875 + - UseRegexCountAnalyzer +helpviewer_keywords: + - CA1875 +dev_langs: + - CSharp + - VB +ai-usage: ai-generated +--- + +# CA1875: Use 'Regex.Count' + +| Property | Value | +|-------------------------------------|----------------------------------------| +| **Rule ID** | CA1875 | +| **Title** | Use `Regex.Count` | +| **Category** | [Performance](performance-warnings.md) | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default in .NET 10** | As suggestion | + +## Cause + +The property of the `MatchCollection` from is used to get the count of matches. + +## Rule description + + is simpler and faster than `Regex.Matches(...).Count`. The `Count()` method is optimized for counting matches without materializing the full . Calling `Matches()` and then accessing `.Count` does unnecessary work that can impact performance. + +## How to fix violations + +Replace calls to `Regex.Matches(...).Count` with `Regex.Count(...)`. + +A *code fix* that automatically performs this transformation is available. + +## Example + +The following code snippet shows a violation of CA1875: + +```csharp +using System.Text.RegularExpressions; + +class Example +{ + public int CountWords(string text) + { + // Violation + return Regex.Matches(text, @"\b\w+\b").Count; + } +} +``` + +```vb +Imports System.Text.RegularExpressions + +Class Example + Public Function CountWords(text As String) As Integer + ' Violation + Return Regex.Matches(text, "\b\w+\b").Count + End Function +End Class +``` + +The following code snippet fixes the violation: + +```csharp +using System.Text.RegularExpressions; + +class Example +{ + public int CountWords(string text) + { + // Fixed + return Regex.Count(text, @"\b\w+\b"); + } +} +``` + +```vb +Imports System.Text.RegularExpressions + +Class Example + Public Function CountWords(text As String) As Integer + ' Fixed + Return Regex.Count(text, "\b\w+\b") + End Function +End Class +``` + +## When to suppress warnings + +It's safe to suppress a warning from this rule if performance isn't a concern or if you're targeting a version of .NET that doesn't include `Regex.Count` (prior to .NET 7). + +## 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 CA1875 +// The code that's violating the rule is on this line. +#pragma warning restore CA1875 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_diagnostic.CA1875.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../suppress-warnings.md). + +## See also + +- [Performance rules](performance-warnings.md) +- +- diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2023.md b/docs/fundamentals/code-analysis/quality-rules/ca2023.md new file mode 100644 index 0000000000000..6cab8749d689e --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/ca2023.md @@ -0,0 +1,166 @@ +--- +title: "CA2023: Invalid braces in message template (code analysis)" +description: "Learn about code analysis rule CA2023: Invalid braces in message template" +ms.date: 10/27/2025 +ms.topic: reference +f1_keywords: + - CA2023 + - InvalidBracesInMessageTemplateAnalyzer +helpviewer_keywords: + - CA2023 +dev_langs: + - CSharp + - VB +ai-usage: ai-generated +--- + +# CA2023: Invalid braces in message template + +| Property | Value | +|-------------------------------------|------------------------------------------| +| **Rule ID** | CA2023 | +| **Title** | Invalid braces in message template | +| **Category** | [Reliability](reliability-warnings.md) | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default in .NET 9** | As warning | + +## Cause + +The braces present in the message template are invalid. Ensure any braces in the message template are valid opening/closing braces, or are escaped. + +## Rule description + +Logging message templates use curly braces `{` and `}` to denote named placeholders for values. Invalid brace usage in message templates can result in runtime exceptions or unexpected logging behavior. This rule detects: + +- Unmatched opening or closing braces. +- Nested braces that aren't properly escaped. +- Other malformed brace patterns. + +## How to fix violations + +To fix a violation of this rule: + +- Ensure all opening braces `{` have a corresponding closing brace `}`. +- Escape literal braces by doubling them: `{{` for `{` and `}}` for `}`. +- Fix any nested or malformed brace patterns. + +## Example + +The following code snippet shows violations of CA2023: + +```csharp +using Microsoft.Extensions.Logging; + +class Example +{ + private readonly ILogger _logger; + + public Example(ILogger logger) + { + _logger = logger; + } + + public void LogData(string name, int value) + { + // Violation: unmatched opening brace. + _logger.LogInformation("Processing {Name with value {Value}", name, value); + + // Violation: unmatched closing brace. + _logger.LogInformation("Processing Name} with value {Value}", name, value); + } +} +``` + +```vb +Imports Microsoft.Extensions.Logging + +Class Example + Private ReadOnly _logger As ILogger + + Public Sub New(logger As ILogger(Of Example)) + _logger = logger + End Sub + + Public Sub LogData(name As String, value As Integer) + ' Violation: unmatched opening brace. + _logger.LogInformation("Processing {Name with value {Value}", name, value) + + ' Violation: unmatched closing brace. + _logger.LogInformation("Processing Name} with value {Value}", name, value) + End Sub +End Class +``` + +The following code snippet fixes the violations: + +```csharp +using Microsoft.Extensions.Logging; + +class Example +{ + private readonly ILogger _logger; + + public Example(ILogger logger) + { + _logger = logger; + } + + public void LogData(string name, int value) + { + // Fixed: proper braces. + _logger.LogInformation("Processing {Name} with value {Value}", name, value); + + // Fixed: escaped literal braces. + _logger.LogInformation("Processing {{Name}} with value {Value}", name, value); + } +} +``` + +```vb +Imports Microsoft.Extensions.Logging + +Class Example + Private ReadOnly _logger As ILogger + + Public Sub New(logger As ILogger(Of Example)) + _logger = logger + End Sub + + Public Sub LogData(name As String, value As Integer) + ' Fixed: proper braces. + _logger.LogInformation("Processing {Name} with value {Value}", name, value) + + ' Fixed: escaped literal braces. + _logger.LogInformation("Processing {{Name}} with value {Value}", name, value) + End Sub +End Class +``` + +## When to suppress warnings + +Don't suppress a warning from this rule. Invalid braces in message templates can cause run-time exceptions or incorrect log 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 CA2023 +// The code that's violating the rule is on this line. +#pragma warning restore CA2023 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_diagnostic.CA2023.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../suppress-warnings.md). + +## See also + +- [Reliability rules](reliability-warnings.md) +- [High-performance logging in .NET](../../../core/extensions/high-performance-logging.md) +- [Logging in .NET](../../../core/extensions/logging.md) diff --git a/docs/fundamentals/code-analysis/quality-rules/index.md b/docs/fundamentals/code-analysis/quality-rules/index.md index 009e27c997022..720c1eb06c983 100644 --- a/docs/fundamentals/code-analysis/quality-rules/index.md +++ b/docs/fundamentals/code-analysis/quality-rules/index.md @@ -77,7 +77,7 @@ The following table lists code quality analysis rules. > | [CA1416: Validate platform compatibility](ca1416.md) | Using platform-dependent APIs on a component makes the code no longer work across all platforms. | > | [CA1417: Do not use `OutAttribute` on string parameters for P/Invokes](ca1417.md) | String parameters passed by value with the `OutAttribute` can destabilize the runtime if the string is an interned string. | > | [CA1418: Use valid platform string](ca1418.md) | Platform compatibility analyzer requires a valid platform name and version. | -> | [CA1419: Provide a parameterless constructor that is as visible as the containing type for concrete types derived from 'System.Runtime.InteropServices.SafeHandle'](ca1419.md) | Providing a parameterless constructor that is as visible as the containing type for a type derived from `System.Runtime.InteropServices.SafeHandle` enables better performance and usage with source-generated interop solutions. | +> | [CA1419: Provide a parameterless constructor that is as visible as the containing type for concrete types derived from `System.Runtime.InteropServices.SafeHandle`](ca1419.md) | Providing a parameterless constructor that is as visible as the containing type for a type derived from `System.Runtime.InteropServices.SafeHandle` enables better performance and usage with source-generated interop solutions. | > | [CA1420: Property, type, or attribute requires runtime marshalling](ca1420.md) | Using features that require runtime marshalling when runtime marshalling is disabled will result in run-time exceptions. | > | [CA1421: Method uses runtime marshalling when DisableRuntimeMarshallingAttribute is applied](ca1421.md) | A method uses runtime marshalling, and runtime marshalling is explicitly disabled. | > | [CA1422: Validate platform compatibility](ca1422.md) | Calling an API that's obsolete in a given OS (version) from a call site that's reachable from that OS (version) is not recommended. | @@ -137,17 +137,17 @@ The following table lists code quality analysis rules. > | [CA1832: Use AsSpan or AsMemory instead of Range-based indexers for getting ReadOnlySpan or ReadOnlyMemory portion of an array](ca1832.md) | When using a range-indexer on an array and implicitly assigning the value to a or type, the method will be used instead of , which produces a copy of requested portion of the array. | > | [CA1833: Use AsSpan or AsMemory instead of Range-based indexers for getting Span or Memory portion of an array](ca1833.md) | When using a range-indexer on an array and implicitly assigning the value to a or type, the method will be used instead of , which produces a copy of requested portion of the array. | > | [CA1834: Use StringBuilder.Append(char) for single character strings](ca1834.md) | has an `Append` overload that takes a `char` as its argument. Prefer calling the `char` overload for performance reasons. | -> | [CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'](ca1835.md) | 'Stream' has a 'ReadAsync' overload that takes a 'Memory<Byte>' as the first argument, and a 'WriteAsync' overload that takes a 'ReadOnlyMemory<Byte>' as the first argument. Prefer calling the memory based overloads, which are more efficient. | +> | [CA1835: Prefer the `Memory`-based overloads for `ReadAsync` and `WriteAsync`](ca1835.md) | `Stream` has a `ReadAsync` overload that takes a `Memory` as the first argument, and a `WriteAsync` overload that takes a `ReadOnlyMemory` as the first argument. Prefer calling the memory based overloads, which are more efficient. | > | [CA1836: Prefer `IsEmpty` over `Count` when available](ca1836.md) | Prefer `IsEmpty` property that is more efficient than `Count`, `Length`, or to determine whether the object contains or not any items. | > | [CA1837: Use `Environment.ProcessId` instead of `Process.GetCurrentProcess().Id`](ca1837.md) | `Environment.ProcessId` is simpler and faster than `Process.GetCurrentProcess().Id`. | -> | [CA1838: Avoid `StringBuilder` parameters for P/Invokes](ca1838.md) | Marshalling of 'StringBuilder' always creates a native buffer copy, resulting in multiple allocations for one marshalling operation. | +> | [CA1838: Avoid `StringBuilder` parameters for P/Invokes](ca1838.md) | Marshalling of `StringBuilder` always creates a native buffer copy, resulting in multiple allocations for one marshalling operation. | > | [CA1839: Use Environment.ProcessPath instead of Process.GetCurrentProcess().MainModule.FileName](ca1839.md) | `Environment.ProcessPath` is simpler and faster than `Process.GetCurrentProcess().MainModule.FileName`. | > | [CA1840: Use Environment.CurrentManagedThreadId instead of Thread.CurrentThread.ManagedThreadId](ca1840.md) | `Environment.CurrentManagedThreadId` is more compact and efficient than `Thread.CurrentThread.ManagedThreadId`. | > | [CA1841: Prefer Dictionary Contains methods](ca1841.md) | Calling `Contains` on the `Keys` or `Values` collection might often be more expensive than calling `ContainsKey` or `ContainsValue` on the dictionary itself. | -> | [CA1842: Do not use 'WhenAll' with a single task](ca1842.md) | Using `WhenAll` with a single task might result in performance loss. Await or return the task instead. | -> | [CA1843: Do not use 'WaitAll' with a single task](ca1843.md) | Using `WaitAll` with a single task might result in performance loss. Await or return the task instead. | -> | [CA1844: Provide memory-based overrides of async methods when subclassing 'Stream'](ca1844.md) | To improve performance, override the memory-based async methods when subclassing 'Stream'. Then implement the array-based methods in terms of the memory-based methods. | -> | [CA1845: Use span-based 'string.Concat'](ca1845.md) | It is more efficient to use `AsSpan` and `string.Concat`, instead of `Substring` and a concatenation operator. | +> | [CA1842: Do not use `WhenAll` with a single task](ca1842.md) | Using `WhenAll` with a single task might result in performance loss. Await or return the task instead. | +> | [CA1843: Do not use `WaitAll` with a single task](ca1843.md) | Using `WaitAll` with a single task might result in performance loss. Await or return the task instead. | +> | [CA1844: Provide memory-based overrides of async methods when subclassing `Stream`](ca1844.md) | To improve performance, override the memory-based async methods when subclassing `Stream`. Then implement the array-based methods in terms of the memory-based methods. | +> | [CA1845: Use span-based `string.Concat`](ca1845.md) | It is more efficient to use `AsSpan` and `string.Concat`, instead of `Substring` and a concatenation operator. | > | [CA1846: Prefer `AsSpan` over `Substring`](ca1846.md) | `AsSpan` is more efficient than `Substring`. `Substring` performs an O(n) string copy, while `AsSpan` does not and has a constant cost. `AsSpan` also does not perform any heap allocations. | > | [CA1847: Use char literal for a single character lookup](ca1847.md) | Use `String.Contains(char)` instead of `String.Contains(string)` when searching for a single character. | > | [CA1848: Use the LoggerMessage delegates](ca1848.md) | For improved performance, use the `LoggerMessage` delegates. | @@ -155,24 +155,27 @@ The following table lists code quality analysis rules. > | [CA1850: Prefer static `HashData` method over `ComputeHash`](ca1850.md) | It's more efficient to use the static `HashData` method over creating and managing a `HashAlgorithm` instance to call `ComputeHash`. | > | [CA1851: Possible multiple enumerations of `IEnumerable` collection](ca1851.md) | Possible multiple enumerations of `IEnumerable` collection. Consider using an implementation that avoids multiple enumerations. | > | [CA1852: Seal internal types](ca1852.md) | A type that's not accessible outside its assembly and has no subtypes within its containing assembly is not sealed. | -> | [CA1853: Unnecessary call to 'Dictionary.ContainsKey(key)'](ca1853.md) | There's no need to guard `Dictionary.Remove(key)` with `Dictionary.ContainsKey(key)`. already checks whether the key exists and doesn't throw if it doesn't exist. | -> | [CA1854: Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method](ca1854.md) | Prefer 'TryGetValue' over a Dictionary indexer access guarded by a 'ContainsKey' check. 'ContainsKey' and the indexer both look up the key, so using 'TryGetValue' avoids the extra lookup. | +> | [CA1853: Unnecessary call to `Dictionary.ContainsKey(key)`](ca1853.md) | There's no need to guard `Dictionary.Remove(key)` with `Dictionary.ContainsKey(key)`. already checks whether the key exists and doesn't throw if it doesn't exist. | +> | [CA1854: Prefer the `IDictionary.TryGetValue(TKey, out TValue)` method](ca1854.md) | Prefer `TryGetValue` over a Dictionary indexer access guarded by a `ContainsKey` check. `ContainsKey` and the indexer both look up the key, so using `TryGetValue` avoids the extra lookup. | > | [CA1855: Use Span\.Clear() instead of Span\.Fill()](ca1855.md) | It's more efficient to call than to call to fill the elements of the span with a default value. | > | [CA1856: Incorrect usage of ConstantExpected attribute](ca1856.md) | The attribute is not applied correctly on a parameter. | > | [CA1857: The parameter expects a constant for optimal performance](ca1857.md) | An invalid argument is passed to a parameter that's annotated with . | > | [CA1858: Use StartsWith instead of IndexOf](ca1858.md) | It's more efficient to call than to call to check whether a string starts with a given prefix. | > | [CA1859: Use concrete types when possible for improved performance](ca1859.md) | Code uses interface types or abstract types, leading to unnecessary interface calls or virtual calls. | -> | [CA1860: Avoid using 'Enumerable.Any()' extension method](ca1860.md) | It's more efficient and clearer to use `Length`, `Count`, or `IsEmpty` (if possible) than to call to determine whether a collection type has any elements. | -> | [CA1861: Avoid constant arrays as arguments](ca1861.md) | Constant arrays passed as arguments are not reused which implies a performance overhead. Consider extracting them to 'static readonly' fields to improve performance. | -> | [CA1862: Use the 'StringComparison' method overloads to perform case-insensitive string comparisons](ca1862.md) | When code calls or to perform a case-insensitive string comparison, an unnecessary allocation is performed. | -> | [CA1863: Use 'CompositeFormat'](ca1863.md) | To reduce the formatting cost, cache and use a instance as the argument to `String.Format` or `StringBuilder.AppendFormat`. | -> | [CA1864: Prefer the 'IDictionary.TryAdd(TKey, TValue)' method](ca1864.md) | Both and perform a lookup, which is redundant. It's is more efficient to call , which returns a `bool` indicating if the value was added or not. `TryAdd` doesn't overwrite the key's value if the key is already present. | +> | [CA1860: Avoid using `Enumerable.Any()` extension method](ca1860.md) | It's more efficient and clearer to use `Length`, `Count`, or `IsEmpty` (if possible) than to call to determine whether a collection type has any elements. | +> | [CA1861: Avoid constant arrays as arguments](ca1861.md) | Constant arrays passed as arguments are not reused which implies a performance overhead. Consider extracting them to `static readonly` fields to improve performance. | +> | [CA1862: Use the `StringComparison` method overloads to perform case-insensitive string comparisons](ca1862.md) | When code calls or to perform a case-insensitive string comparison, an unnecessary allocation is performed. | +> | [CA1863: Use `CompositeFormat`](ca1863.md) | To reduce the formatting cost, cache and use a instance as the argument to `String.Format` or `StringBuilder.AppendFormat`. | +> | [CA1864: Prefer the `IDictionary.TryAdd(TKey, TValue)` method](ca1864.md) | Both and perform a lookup, which is redundant. It's is more efficient to call , which returns a `bool` indicating if the value was added or not. `TryAdd` doesn't overwrite the key's value if the key is already present. | > | [CA1865-CA1867: Use char overload](ca1865-ca1867.md) | The char overload is a better performing overload for a string with a single char. | -> | [CA1868: Unnecessary call to 'Contains' for sets](ca1868.md) | Both and perform a lookup, which makes it redundant to call beforehand. It's more efficient to call or directly, which returns a Boolean value indicating whether the item was added or removed. | -> | [CA1869: Cache and reuse 'JsonSerializerOptions' instances](ca1869.md) | Using a local instance of for serialization or deserialization can substantially degrade the performance of your application if your code executes multiple times, since System.Text.Json internally caches serialization-related metadata into the provided instance. | -> | [CA1870: Use a cached 'SearchValues' instance](ca1870.md) | Using a cached instance is more efficient than passing values to 'IndexOfAny' or 'ContainsAny' directly. | -> | [CA1871: Do not pass a nullable struct to 'ArgumentNullException.ThrowIfNull'](ca1871.md) | 'ArgumentNullException.ThrowIfNull' accepts an 'object', so passing a nullable struct might cause the value to be boxed. | -> | [CA1872: Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString'](ca1872.md) | Use or when encoding bytes to a hexadecimal string representation. These methods are more efficient and allocation-friendly than using in combination with to replace dashes and . | +> | [CA1868: Unnecessary call to `Contains` for sets](ca1868.md) | Both and perform a lookup, which makes it redundant to call beforehand. It's more efficient to call or directly, which returns a Boolean value indicating whether the item was added or removed. | +> | [CA1869: Cache and reuse `JsonSerializerOptions` instances](ca1869.md) | Using a local instance of for serialization or deserialization can substantially degrade the performance of your application if your code executes multiple times, since System.Text.Json internally caches serialization-related metadata into the provided instance. | +> | [CA1870: Use a cached `SearchValues` instance](ca1870.md) | Using a cached instance is more efficient than passing values to `IndexOfAny` or `ContainsAny` directly. | +> | [CA1871: Do not pass a nullable struct to `ArgumentNullException.ThrowIfNull`](ca1871.md) | `ArgumentNullException.ThrowIfNull` accepts an `object`, so passing a nullable struct might cause the value to be boxed. | +> | [CA1872: Prefer `Convert.ToHexString` and `Convert.ToHexStringLower` over call chains based on `BitConverter.ToString`](ca1872.md) | Use or when encoding bytes to a hexadecimal string representation. These methods are more efficient and allocation-friendly than using in combination with to replace dashes and . | +> | [CA1873: Avoid potentially expensive logging](ca1873.md) | In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for logging arguments. | +> | [CA1874: Use `Regex.IsMatch`](ca1874.md) | `Regex.IsMatch` is simpler and faster than `Regex.Match(...).Success`. | +> | [CA1875: Use `Regex.Count`](ca1875.md) | `Regex.Count` is simpler and faster than `Regex.Matches(...).Count`. | > | [CA2000: Dispose objects before losing scope](ca2000.md) | Because an exceptional event might occur that will prevent the finalizer of an object from running, the object should be explicitly disposed before all references to it are out of scope. | > | [CA2002: Do not lock on objects with weak identity](ca2002.md) |An object is said to have a weak identity when it can be directly accessed across application domain boundaries. A thread that tries to acquire a lock on an object that has a weak identity can be blocked by a second thread in a different application domain that has a lock on the same object. | > | [CA2007: Do not directly await a Task](ca2007.md) | An asynchronous method [awaits](../../../csharp/language-reference/operators/await.md) a directly. When an asynchronous method awaits a directly, continuation occurs in the same thread that created the task. This behavior can be costly in terms of performance and can result in a deadlock on the UI thread. Consider calling to signal your intention for continuation. | @@ -190,6 +193,7 @@ The following table lists code quality analysis rules. > | [CA2020: Prevent behavioral change caused by built-in operators of IntPtr/UIntPtr](ca2020.md) | Some built-in operators added in .NET 7 behave differently than the user-defined operators in .NET 6 and earlier versions. Some operators that used to throw in unchecked context while overflowing don't throw anymore unless wrapped within checked context. Some operators that previously didn't throw in checked context now throw unless wrapped within unchecked context. | > | [CA2021: Don't call Enumerable.Cast\ or Enumerable.OfType\ with incompatible types](ca2021.md) | A call to or specifies a type parameter that's incompatible with the type of the input collection. | > | [CA2022: Avoid inexact read with Stream.Read](ca2022.md) | A call to `Stream.Read` might return fewer bytes than requested, resulting in unreliable code if the return value isn't checked. | +> | [CA2023: Invalid braces in message template](ca2023.md) | The braces present in the message template are invalid. Ensure any braces in the message template are valid opening/closing braces, or are escaped. | > | [CA2024: Do not use StreamReader.EndOfStream in async methods](ca2024.md) | The property can cause unintended synchronous blocking when no data is buffered. Instead, use directly, which returns `null` when reaching the end of the stream. | > | [CA2025: Do not pass `IDisposable` instances into unawaited tasks](ca2025.md) | Unawaited tasks that use `IDisposable` instances might use those instances long after they have been disposed. Ensure tasks using those instances are completed before the instances are disposed. | > | [CA2100: Review SQL queries for security vulnerabilities](ca2100.md) | A method sets the System.Data.IDbCommand.CommandText property by using a string that is built from a string argument to the method. This rule assumes that the string argument contains user input. A SQL command string that is built from user input is vulnerable to SQL injection attacks. | @@ -234,14 +238,14 @@ The following table lists code quality analysis rules. > | [CA2254: Template should be a static expression](ca2254.md) | The logging message template should not vary between calls. | > | [CA2255: The `ModuleInitializer` attribute should not be used in libraries](ca2255.md) | Module initializers are intended to be used by application code to ensure an application's components are initialized before the application code begins executing. | > | [CA2256: All members declared in parent interfaces must have an implementation in a DynamicInterfaceCastableImplementation-attributed interface](ca2256.md) | Types attributed with `DynamicInterfaceCastableImplementationAttribute` act as an interface implementation for a type that implements the `IDynamicInterfaceCastable` type. As a result, it must provide an implementation of all of the members defined in the inherited interfaces, because the type that implements `IDynamicInterfaceCastable` will not provide them otherwise. | -> | [CA2257: Members defined on an interface with 'DynamicInterfaceCastableImplementationAttribute' should be 'static'](ca2257.md) | Since a type that implements `IDynamicInterfaceCastable` might not implement a dynamic interface in metadata, calls to an instance interface member that is not an explicit implementation defined on this type are likely to fail at run time. Mark new interface members `static` to avoid run-time errors. | -> | [CA2258: Providing a 'DynamicInterfaceCastableImplementation' interface in Visual Basic is unsupported](ca2258.md) | Providing a functional `DynamicInterfaceCastableImplementationAttribute`-attributed interface requires the Default Interface Members feature, which is unsupported in Visual Basic. | +> | [CA2257: Members defined on an interface with `DynamicInterfaceCastableImplementationAttribute` should be `static`](ca2257.md) | Since a type that implements `IDynamicInterfaceCastable` might not implement a dynamic interface in metadata, calls to an instance interface member that is not an explicit implementation defined on this type are likely to fail at run time. Mark new interface members `static` to avoid run-time errors. | +> | [CA2258: Providing a `DynamicInterfaceCastableImplementation` interface in Visual Basic is unsupported](ca2258.md) | Providing a functional `DynamicInterfaceCastableImplementationAttribute`-attributed interface requires the Default Interface Members feature, which is unsupported in Visual Basic. | > | [CA2259: Ensure `ThreadStatic` is only used with static fields](ca2259.md) | only affects `static` (`Shared` in Visual Basic) fields. When applied to instance fields, the attribute has no impact on behavior. | > | [CA2260: Implement generic math interfaces correctly](ca2260.md) | Generic math interfaces require the derived type itself to be used for the self-recurring type parameter. | > | [CA2261: Do not use `ConfigureAwaitOptions.SuppressThrowing` with `Task`](ca2261.md) | The `ConfigureAwaitOptions.SuppressThrowing` option isn't supported by the generic `Task`, since that might lead to returning an invalid `TResult`. | > | [CA2262: Set `MaxResponseHeadersLength` properly](ca2262.md) | Make sure the `MaxResponseHeadersLength` value is provided correctly. This value is measured in kilobytes. | > | [CA2263: Prefer generic overload when type is known](ca2263.md) | Using a generic overload is preferable to passing a argument when the type is known, because they promote cleaner and more type-safe code with improved compile-time checks. | -> | [CA2264: Do not pass a non-nullable value to 'ArgumentNullException.ThrowIfNull'](ca2264.md) | 'ArgumentNullException.ThrowIfNull' throws when the passed argument is 'null'. Certain constructs like non-nullable structs, and 'nameof()' and 'new' expressions are known to never be null, so 'ArgumentNullException.ThrowIfNull' will never throw. | +> | [CA2264: Do not pass a non-nullable value to `ArgumentNullException.ThrowIfNull`](ca2264.md) | `ArgumentNullException.ThrowIfNull` throws when the passed argument is `null`. Certain constructs like non-nullable structs, and `nameof()` and `new` expressions are known to never be null, so `ArgumentNullException.ThrowIfNull` will never throw. | > | [CA2265: Do not compare `Span` to `null` or `default`](ca2265.md) | Comparing a span to `null` or `default` might not do what you intended. `default` and the `null` literal are implicitly converted to `Span.Empty`. | > | [CA2300: Do not use insecure deserializer BinaryFormatter](ca2300.md) | Insecure deserializers are vulnerable when deserializing untrusted data. An attacker could modify the serialized data to include unexpected types to inject objects with malicious side effects. | > | [CA2301: Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder](ca2301.md) | Insecure deserializers are vulnerable when deserializing untrusted data. An attacker could modify the serialized data to include unexpected types to inject objects with malicious side effects. | @@ -336,23 +340,23 @@ The following table lists code quality analysis rules. > | [CA5405: Do not always skip token validation in delegates](ca5405.md) | The callback assigned to `AudienceValidator` or `LifetimeValidator` always returns `true`. | > | [IL3000: Avoid accessing Assembly file path when publishing as a single file](../../../core/deploying/single-file/warnings/il3000.md) | Avoid accessing Assembly file path when publishing as a single file. | > | [IL3001: Avoid accessing Assembly file path when publishing as a single-file](../../../core/deploying/single-file/warnings/il3001.md) | Avoid accessing Assembly file path when publishing as a single file. | -> | [IL3002: Avoid calling members annotated with 'RequiresAssemblyFilesAttribute' when publishing as a single file](../../../core/deploying/single-file/warnings/il3002.md) | Avoid calling members annotated with 'RequiresAssemblyFilesAttribute' when publishing as a single file| -> | [IL3003: 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides.](../../../core/deploying/single-file/warnings/il3003.md) | 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides.| +> | [IL3002: Avoid calling members annotated with `RequiresAssemblyFilesAttribute` when publishing as a single file](../../../core/deploying/single-file/warnings/il3002.md) | Avoid calling members annotated with `RequiresAssemblyFilesAttribute` when publishing as a single file| +> | [IL3003: `RequiresAssemblyFilesAttribute` annotations must match across all interface implementations or overrides.](../../../core/deploying/single-file/warnings/il3003.md) | `RequiresAssemblyFilesAttribute` annotations must match across all interface implementations or overrides.| > | [IL3005: `RequiresAssemblyFilesAttribute` cannot be placed directly on application entry point.](../../../core/deploying/single-file/warnings/il3005.md)|`RequiresAssemblyFilesAttribute` cannot be placed directly on application entry point. | ## Legend The following table shows the type of information that is provided for each rule in the reference documentation. -|Item|Description| -|----------|-----------------| -|Type|The TypeName for the rule.| -| **Rule ID** |The unique identifier for the rule. RuleId and Category are used for in-source suppression of a warning.| -| **Category** |The category of the rule, for example, security.| -| **Fix is breaking or non-breaking** |Whether the fix for a violation of the rule is a breaking change. Breaking change means that an assembly that has a dependency on the target that caused the violation will not recompile with the new fixed version or might fail at run time because of the change. When multiple fixes are available and at least one fix is a breaking change and one fix is not, both 'Breaking' and 'Non-breaking' are specified.| -|Cause|The specific managed code that causes the rule to generate a warning.| -|Description|Discusses the issues that are behind the warning.| -|How to fix violations|Explains how to change the source code to satisfy the rule and prevent it from generating a warning.| -|When to suppress warnings|Describes when it is safe to suppress a warning from the rule.| -|Example code|Examples that violate the rule and corrected examples that satisfy the rule.| -|Related rules|Related rules.| +| Item | Description | +|--------------|--------------------------------------------------| +| Type | The TypeName for the rule. | +| **Rule ID** | The unique identifier for the rule. RuleId and Category are used for in-source suppression of a warning. | +| **Category** | The category of the rule, for example, security. | +| **Fix is breaking or non-breaking** | Whether the fix for a violation of the rule is a breaking change. Breaking change means that an assembly that has a dependency on the target that caused the violation will not recompile with the new fixed version or might fail at run time because of the change. When multiple fixes are available and at least one fix is a breaking change and one fix is not, both 'Breaking' and 'Non-breaking' are specified. | +| Cause | The specific managed code that causes the rule to generate a warning. | +| Description | Discusses the issues that are behind the warning. | +| How to fix violations | Explains how to change the source code to satisfy the rule and prevent it from generating a warning. | +| When to suppress warnings | Describes when it is safe to suppress a warning from the rule. | +| Example code | Examples that violate the rule and corrected examples that satisfy the rule. | +| Related rules | Related rules. | diff --git a/docs/fundamentals/code-analysis/quality-rules/performance-warnings.md b/docs/fundamentals/code-analysis/quality-rules/performance-warnings.md index dc28cd1200fb5..d46d9b9608e87 100644 --- a/docs/fundamentals/code-analysis/quality-rules/performance-warnings.md +++ b/docs/fundamentals/code-analysis/quality-rules/performance-warnings.md @@ -1,7 +1,7 @@ --- title: Performance rules (code analysis) description: "Learn about code analysis performance rules." -ms.date: 11/15/2023 +ms.date: 10/27/2025 f1_keywords: - vs.codeanalysis.performancerules helpviewer_keywords: @@ -19,7 +19,7 @@ Performance rules support high-performance libraries and applications. ## In this section | Rule | Description | -| - | - | +|------|-------------| | [CA1802: Use Literals Where Appropriate](ca1802.md) | A field is declared static and read-only (Shared and ReadOnly in Visual Basic), and is initialized with a value that is computable at compile time. Because the value that is assigned to the targeted field is computable at compile time, change the declaration to a const (Const in Visual Basic) field so that the value is computed at compile time instead of at run time. | | [CA1805: Do not initialize unnecessarily](ca1805.md) | The .NET runtime initializes all fields of reference types to their default values before running the constructor. In most cases, explicitly initializing a field to its default value is redundant, which adds to maintenance costs and may degrade performance (such as with increased assembly size). | | [CA1806: Do not ignore method results](ca1806.md) | A new object is created but never used, or a method that creates and returns a new string is called and the new string is never used, or a Component Object Model (COM) or P/Invoke method returns an HRESULT or error code that is never used. | @@ -80,3 +80,6 @@ Performance rules support high-performance libraries and applications. | [CA1870: Use a cached 'SearchValues' instance](ca1870.md) | Using a cached instance is more efficient than passing values to 'IndexOfAny' or 'ContainsAny' directly. | | [CA1871: Do not pass a nullable struct to 'ArgumentNullException.ThrowIfNull'](ca1871.md) | 'ArgumentNullException.ThrowIfNull' accepts an 'object', so passing a nullable struct might cause the value to be boxed. | | [CA1872: Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString'](ca1872.md) | Use or when encoding bytes to a hexadecimal string representation. These methods are more efficient and allocation-friendly than using in combination with to replace dashes and . | +| [CA1873: Avoid potentially expensive logging](ca1873.md) | When logging methods are called, their arguments are evaluated regardless of whether the logging level is enabled. This can result in expensive operations being executed even when the log message won't be written. For better performance, guard expensive logging calls with a check to or use the `LoggerMessage` pattern. | +| [CA1874: Use 'Regex.IsMatch'](ca1874.md) | is simpler and faster than `Regex.Match(...).Success`. | +| [CA1875: Use 'Regex.Count'](ca1875.md) | is simpler and faster than `Regex.Matches(...).Count`. | diff --git a/docs/fundamentals/code-analysis/quality-rules/reliability-warnings.md b/docs/fundamentals/code-analysis/quality-rules/reliability-warnings.md index 37a93a288af35..6437efebefa8a 100644 --- a/docs/fundamentals/code-analysis/quality-rules/reliability-warnings.md +++ b/docs/fundamentals/code-analysis/quality-rules/reliability-warnings.md @@ -1,22 +1,20 @@ --- title: Reliability rules (code analysis) description: "Learn about code analysis reliability rules." -ms.date: 11/16/2023 +ms.date: 10/27/2025 f1_keywords: - vs.codeanalysis.reliabilityrules helpviewer_keywords: - rules, reliability - reliability rules - managed code analysis rules, reliability rules -author: gewarren -ms.author: gewarren --- # Reliability rules Reliability rules support library and application reliability, such as correct memory and thread usage. The reliability rules include: -|Rule|Description| -|----------|-----------------| +| Rule | Description | +|------|-------------| | [CA2000: Dispose objects before losing scope](ca2000.md) | Because an exceptional event might occur that will prevent the finalizer of an object from running, the object should be explicitly disposed before all references to it are out of scope. | | [CA2002: Do not lock on objects with weak identity](ca2002.md) | An object is said to have a weak identity when it can be directly accessed across application domain boundaries. A thread that tries to acquire a lock on an object that has a weak identity can be blocked by a second thread in a different application domain that has a lock on the same object. | | [CA2007: Do not directly await a Task](ca2007.md) | An asynchronous method [awaits](../../../csharp/language-reference/operators/await.md) a directly. | @@ -34,5 +32,6 @@ Reliability rules support library and application reliability, such as correct m | [CA2020: Prevent behavioral change caused by built-in operators of IntPtr/UIntPtr](ca2020.md) | Some built-in operators added in .NET 7 behave differently than the user-defined operators in .NET 6 and earlier versions. Some operators that used to throw in unchecked context while overflowing don't throw anymore unless wrapped within checked context. Some operators that previously didn't throw in checked context now throw unless wrapped within unchecked context. | | [CA2021: Don't call Enumerable.Cast\ or Enumerable.OfType\ with incompatible types](ca2021.md) | A call to or specifies a type parameter that's incompatible with the type of the input collection. | | [CA2022: Avoid inexact read with Stream.Read](ca2022.md) | A call to `Stream.Read` might return fewer bytes than requested, resulting in unreliable code if the return value isn't checked. | +| [CA2023: Invalid braces in message template](ca2023.md) | Logging message templates use curly braces `{` and `}` to denote named placeholders for values. Invalid brace usage in message templates can result in runtime exceptions or unexpected logging behavior. | | [CA2024: Do not use StreamReader.EndOfStream in async methods](ca2024.md) | The property can cause unintended synchronous blocking when no data is buffered. Instead, use directly, which returns `null` when reaching the end of the stream. | | [CA2025: Do not pass `IDisposable` instances into unawaited tasks](ca2025.md) | Unawaited tasks that use `IDisposable` instances might use those instances long after they have been disposed. Ensure tasks using those instances are completed before the instances are disposed. | diff --git a/docs/navigate/tools-diagnostics/toc.yml b/docs/navigate/tools-diagnostics/toc.yml index 6074077eebbdf..44bf78dba9ca5 100644 --- a/docs/navigate/tools-diagnostics/toc.yml +++ b/docs/navigate/tools-diagnostics/toc.yml @@ -3277,6 +3277,12 @@ items: href: ../../fundamentals/code-analysis/quality-rules/ca1871.md - name: CA1872 href: ../../fundamentals/code-analysis/quality-rules/ca1872.md + - name: CA1873 + href: ../../fundamentals/code-analysis/quality-rules/ca1873.md + - name: CA1874 + href: ../../fundamentals/code-analysis/quality-rules/ca1874.md + - name: CA1875 + href: ../../fundamentals/code-analysis/quality-rules/ca1875.md - name: SingleFile rules items: - name: Overview @@ -3331,6 +3337,8 @@ items: href: ../../fundamentals/code-analysis/quality-rules/ca2021.md - name: CA2022 href: ../../fundamentals/code-analysis/quality-rules/ca2022.md + - name: CA2023 + href: ../../fundamentals/code-analysis/quality-rules/ca2023.md - name: CA2024 href: ../../fundamentals/code-analysis/quality-rules/ca2024.md - name: CA2025