diff --git a/docs/core/compatibility/10.0.md b/docs/core/compatibility/10.0.md index 917d54605a92a..2d92b51f5a69a 100644 --- a/docs/core/compatibility/10.0.md +++ b/docs/core/compatibility/10.0.md @@ -130,6 +130,12 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af | [NUGET_ENABLE_ENHANCED_HTTP_RETRY environment variable removed](sdk/10.0/nuget-enhanced-http-retry-removed.md) | Behavioral change | Preview 6 | | [NuGet logs an error for invalid package IDs](sdk/10.0/nuget-packageid-validation.md) | Behavioral change | RC 1 | +## Serialization + +| Title | Type of change | Introduced version | +|-------|-------------------|--------------------| +| [XmlSerializer no longer ignores properties marked with ObsoleteAttribute](serialization/10/xmlserializer-obsolete-properties.md) | Behavioral change | Preview 1 | + ## Windows Forms | Title | Type of change | Introduced version | diff --git a/docs/core/compatibility/serialization/10/xmlserializer-obsolete-properties.md b/docs/core/compatibility/serialization/10/xmlserializer-obsolete-properties.md new file mode 100644 index 0000000000000..927093eefec28 --- /dev/null +++ b/docs/core/compatibility/serialization/10/xmlserializer-obsolete-properties.md @@ -0,0 +1,92 @@ +--- +title: "Breaking change: XmlSerializer no longer ignores properties marked with ObsoleteAttribute" +description: "Learn about the breaking change in .NET 10 where properties marked with ObsoleteAttribute are now serialized by XmlSerializer instead of being ignored." +ms.date: 10/21/2025 +ai-usage: ai-assisted +ms.custom: https://github.com/dotnet/docs/issues/49054 +--- +# XmlSerializer no longer ignores properties marked with ObsoleteAttribute + +Starting in .NET 10, the behavior of has changed with respect to how it handles properties marked with the attribute. Previously, properties marked with `[Obsolete]` were treated as if they were also marked with `[XmlIgnore]`, causing them to be excluded from XML serialization. This behavior was unintended and has been corrected. + +With this change, properties marked with `[Obsolete]` are now serialized by default unless the property is set to `true`. If `IsError` is `true`, the serializer throws an during creation. Additionally, an AppContext switch, `Switch.System.Xml.IgnoreObsoleteMembers`, has been introduced to allow developers to revert to the previous behavior, if necessary. + +## Version introduced + +.NET 10 Preview 1 + +## Previous behavior + +In previous versions of .NET, properties marked with the `[Obsolete]` attribute were excluded from XML serialization, similar to properties marked with `[XmlIgnore]`. This behavior was unexpected and not aligned with the intended purpose of the `[Obsolete]` attribute, which is to provide compile-time warnings about deprecated APIs. + +```csharp +public class Example +{ + public string NormalProperty { get; set; } = "normal"; + + [Obsolete("This property is deprecated")] + public string ObsoleteProperty { get; set; } = "obsolete"; + + [XmlIgnore] + public string IgnoredProperty { get; set; } = "ignored"; +} + +var obj = new Example(); +var serializer = new XmlSerializer(typeof(Example)); +using var writer = new StringWriter(); +serializer.Serialize(writer, obj); +Console.WriteLine(writer.ToString()); +``` + +**Output before the change:** + +```xml + + normal + +``` + +## New behavior + +Starting in .NET 10, properties marked with `[Obsolete]` are no longer excluded from XML serialization by default. Instead: + +- If the `[Obsolete]` attribute is applied with `IsError = false` (default), the property is serialized normally. +- If the `[Obsolete]` attribute is applied with `IsError = true`, the throws an during serializer creation. + +Using the same code as shown in the previous behavior section, the output after the change is: + +```xml + + normal + obsolete + +``` + +If `[Obsolete(IsError = true)]` is applied to a property, the following exception is thrown during serializer creation: + +> System.InvalidOperationException: Cannot serialize member 'ObsoleteProperty' because it is marked with ObsoleteAttribute and IsError is set to true. + +> [!NOTE] +> Properties that are marked as `[Obsolete]` have always successfully deserialized when data is present in the XML. While this change allows `[Obsolete]` properties to "round trip" from object to XML and back to object, the new behavior affects only the serialization half (object to XML) of the "round trip." + +## Type of breaking change + +This change is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +The previous behavior of treating `[Obsolete]` as equivalent to `[XmlIgnore]` was unintended and inconsistent with the purpose of the `[Obsolete]` attribute. This change ensures that `[Obsolete]` is used solely for its intended purpose of providing compile-time warnings and doesn't affect runtime serialization behavior. The introduction of the AppContext switch allows developers to opt in to the legacy behavior if necessary. + +## Recommended action + +Review your codebase for any reliance on the previous behavior where `[Obsolete]` properties were excluded from XML serialization. If this behavior is still desired, enable the AppContext switch `Switch.System.Xml.IgnoreObsoleteMembers` as follows: + +```csharp +AppContext.SetSwitch("Switch.System.Xml.IgnoreObsoleteMembers", true); +``` + +If any properties are marked with `[Obsolete(IsError = true)]` and are being serialized, update the code to either remove the `[Obsolete]` attribute or set `IsError = false` to avoid runtime exceptions. + +## Affected APIs + +- diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 2b7ed52bc3c3f..ec9c94695b2f9 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -162,6 +162,10 @@ items: href: sdk/10.0/prune-packagereference-privateassets.md - name: Version requirements for .NET 10 SDK href: sdk/10.0/version-requirements.md + - name: Serialization + items: + - name: XmlSerializer no longer ignores properties marked with ObsoleteAttribute + href: serialization/10/xmlserializer-obsolete-properties.md - name: Windows Forms items: - name: API obsoletions diff --git a/docs/fundamentals/code-analysis/quality-rules/ca1720.md b/docs/fundamentals/code-analysis/quality-rules/ca1720.md index 93e737b5c6e8f..0378767cb9528 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca1720.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca1720.md @@ -10,6 +10,8 @@ helpviewer_keywords: - CA1720 author: gewarren ms.author: gewarren +dev_langs: +- CSharp --- # CA1720: Identifiers should not contain type names @@ -91,6 +93,10 @@ Replace the data type identifier in the name of the parameter with either a term Replace the language-specific data type identifier in the name of the member with a term that better describes its meaning, a language-independent equivalent, or a more generic term, such as 'value'. +## Example + +:::code language="csharp" source="snippets/csharp/all-rules/ca1720.cs" id="snippet1"::: + ## When to suppress warnings Occasional use of type-based parameter and member names might be appropriate. However, for new development, no known scenarios occur where you should suppress a warning from this rule. For libraries that have previously shipped, you might have to suppress a warning from this rule. diff --git a/docs/fundamentals/code-analysis/quality-rules/ca1725.md b/docs/fundamentals/code-analysis/quality-rules/ca1725.md index 20ef67d724b9e..3ef7976b6528a 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca1725.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca1725.md @@ -10,6 +10,8 @@ helpviewer_keywords: - ParameterNamesShouldMatchBaseDeclaration author: gewarren ms.author: gewarren +dev_langs: +- CSharp --- # CA1725: Parameter names should match base declaration @@ -35,6 +37,10 @@ Consistent naming of parameters in an override hierarchy increases the usability To fix a violation of this rule, rename the parameter to match the base declaration. The fix is a breaking change for callers who specify the parameter name. +## Example + +:::code language="csharp" source="snippets/csharp/all-rules/ca1725.cs" id="snippet1"::: + ## When to suppress warnings Do not suppress a warning from this rule except for visible methods in libraries that have previously shipped. diff --git a/docs/fundamentals/code-analysis/quality-rules/ca1727.md b/docs/fundamentals/code-analysis/quality-rules/ca1727.md index 7b8bd54b77779..5a56ec4d59c9e 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca1727.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca1727.md @@ -9,6 +9,8 @@ helpviewer_keywords: - CA1727 - LoggerMessageDefineAnalyzer author: Youssef1313 +dev_langs: +- CSharp --- # CA1727: Use PascalCase for named placeholders @@ -32,6 +34,10 @@ A named placeholder used with should Use PascalCase for named placeholders. For example, change `{firstName}` to `{FirstName}`. +## Example + +:::code language="csharp" source="snippets/csharp/all-rules/ca1727.cs" id="snippet1"::: + ## When to suppress warnings It is safe to suppress a warning from this rule. diff --git a/docs/fundamentals/code-analysis/quality-rules/ca1822.md b/docs/fundamentals/code-analysis/quality-rules/ca1822.md index fc63b9fc548af..5091b39f79a92 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca1822.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca1822.md @@ -10,6 +10,8 @@ helpviewer_keywords: - CA1822 author: gewarren ms.author: gewarren +dev_langs: +- CSharp --- # CA1822: Mark members as static @@ -33,6 +35,10 @@ Members that do not access instance data or call instance methods can be marked Mark the member as static (or Shared in Visual Basic) or use 'this'/'Me' in the method body, if appropriate. +## Example + +:::code language="csharp" source="snippets/csharp/all-rules/ca1822.cs" id="snippet1"::: + ## When to suppress warnings It is safe to suppress a warning from this rule for previously shipped code for which the fix would be a breaking change. diff --git a/docs/fundamentals/code-analysis/quality-rules/ca1823.md b/docs/fundamentals/code-analysis/quality-rules/ca1823.md index 2ebc222c53912..9b2b0afeb05dc 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca1823.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca1823.md @@ -10,6 +10,8 @@ helpviewer_keywords: - CA1823 author: gewarren ms.author: gewarren +dev_langs: +- CSharp --- # CA1823: Avoid unused private fields @@ -33,6 +35,10 @@ Private fields were detected that do not appear to be accessed in the assembly. To fix a violation of this rule, remove the field or add code that uses it. +## Example + +:::code language="csharp" source="snippets/csharp/all-rules/ca1823.cs" id="snippet1"::: + ## When to suppress warnings It is safe to suppress a warning from this rule. @@ -60,3 +66,4 @@ For more information, see [How to suppress code analysis warnings](../suppress-w - [CA1812: Avoid uninstantiated internal classes](ca1812.md) - [CA1801: Review unused parameters](ca1801.md) +- [Remove unread private member (IDE0052)](../style-rules/ide0052.md) diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2008.md b/docs/fundamentals/code-analysis/quality-rules/ca2008.md index 68218e9564457..fd0ead2ab8e15 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca2008.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca2008.md @@ -9,6 +9,8 @@ helpviewer_keywords: - CA2008 author: gewarren ms.author: gewarren +dev_langs: +- CSharp --- # CA2008: Do not create tasks without passing a TaskScheduler @@ -42,6 +44,44 @@ For further information and detailed examples, see [New TaskCreationOptions and To fix violations, call the method overload that takes a and explicitly pass in or to make the intent clear. +## Example + +```csharp +// This code violates the rule. +var badTask = Task.Factory.StartNew( + () => + { + // ... + } +); +badTask.ContinueWith( + t => + { + // ... + } +); + +// This code satisfies the rule. +var goodTask = Task.Factory.StartNew( + () => + { + // ... + }, + CancellationToken.None, + TaskCreationOptions.None, + TaskScheduler.Default +); +goodTask.ContinueWith( + t => + { + // ... + }, + CancellationToken.None, + TaskContinuationOptions.None, + TaskScheduler.Default +); +``` + ## When to suppress warnings This warning is intended primarily for libraries, where the code may be executed in arbitrary environments and where code shouldn't make assumptions about the environment or how the caller of the method may be invoking or waiting on it. It may be appropriate to suppress the warning for projects that represent application code rather than library code. diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2012.md b/docs/fundamentals/code-analysis/quality-rules/ca2012.md index d49c77d33b139..4109632a6e8aa 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca2012.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca2012.md @@ -10,6 +10,8 @@ helpviewer_keywords: - "CA2012" author: stephentoub ms.author: stoub +dev_langs: +- CSharp --- # CA2012: Use ValueTasks correctly @@ -37,6 +39,10 @@ In general, ValueTasks should be directly awaited rather than discarded or store For `ValueTask` objects returned from arbitrary member calls, the caller needs to assume that the `ValueTask` must be consumed (for example, awaited) once and only once. However, if the developer also controls the member being invoked and has complete knowledge of its implementation, the developer may know it's safe to suppress the warning, for example, if the return `ValueTask` always wraps a object. +## Example + +:::code language="csharp" source="snippets/csharp/all-rules/ca2012.cs" id="snippet1"::: + ## 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. diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2014.md b/docs/fundamentals/code-analysis/quality-rules/ca2014.md index ed36a1fed65d3..830bba5a67ce9 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca2014.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca2014.md @@ -10,6 +10,8 @@ helpviewer_keywords: - "CA2014" author: stephentoub ms.author: stoub +dev_langs: +- CSharp --- # CA2014: Do not use stackalloc in loops @@ -33,6 +35,10 @@ The C# `stackalloc` expression allocates memory from the current stack frame, an Move the `stackalloc` expression outside of all loops in the method. +## Example + +:::code language="csharp" source="snippets/csharp/all-rules/ca2014.cs" id="snippet1"::: + ## When to suppress warnings It may be safe to suppress the warning when the containing loop or loops are invoked only a finite number of times, such that the overall amount of memory allocated across all `stackalloc` operations is known to be relatively small. diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2016.md b/docs/fundamentals/code-analysis/quality-rules/ca2016.md index 6e16a8dea2ee2..dc6b6b18c36c4 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca2016.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca2016.md @@ -49,7 +49,7 @@ The rule can detect a variety of violations. The following examples show cases t ### Example 1 -The rule will suggest forwarding the `c` parameter from `MyMethod` to the `MyMethodWithDefault` invocation, because the method defines an optional token parameter: +The rule will suggest forwarding the `ct` parameter from `MyMethod` to the `MyMethodWithDefault` invocation, because the method defines an optional token parameter: ```csharp using System.Threading; @@ -62,7 +62,7 @@ namespace ConsoleApp { } - public static void MyMethod(CancellationToken c) + public static void MyMethod(CancellationToken ct) { MyMethodWithDefault(); } @@ -72,13 +72,13 @@ namespace ConsoleApp Fix: -Forward the `c` parameter: +Forward the `ct` parameter: ```csharp - public static void MyMethod(CancellationToken c) - { - MyMethodWithDefault(c); - } +public static void MyMethod(CancellationToken ct) +{ + MyMethodWithDefault(ct); +} ``` If you are not concerned about forwarding cancellation notifications to lower invocations, you can either: @@ -86,24 +86,24 @@ If you are not concerned about forwarding cancellation notifications to lower in Explicitly pass `default`: ```csharp - public static void MyMethod(CancellationToken c) - { - MyMethodWithDefault(default); - } +public static void MyMethod(CancellationToken ct) +{ + MyMethodWithDefault(default); +} ``` Or explicitly pass `CancellationToken.None`: ```csharp - public static void MyMethod(CancellationToken c) - { - MyMethodWithDefault(CancellationToken.None); - } +public static void MyMethod(CancellationToken ct) +{ + MyMethodWithDefault(CancellationToken.None); +} ``` ### Example 2 -The rule will suggest forwarding the `c` parameter from `MyMethod` to the `MyMethodWithOverload` invocation, because the method has an overload that takes a `CancellationToken` parameter: +The rule will suggest forwarding the `ct` parameter from `MyMethod` to the `MyMethodWithOverload` invocation, because the method has an overload that takes a `CancellationToken` parameter: ```csharp using System.Threading; @@ -120,7 +120,7 @@ namespace ConsoleApp { } - public static void MyMethod(CancellationToken c) + public static void MyMethod(CancellationToken ct) { MyMethodWithOverload(); } @@ -130,13 +130,13 @@ namespace ConsoleApp Fix: -Forward the `c` parameter: +Forward the `ct` parameter: ```csharp - public static void MyMethod(CancellationToken c) - { - MyMethodWithOverload(c); - } +public static void MyMethod(CancellationToken ct) +{ + MyMethodWithOverload(ct); +} ``` If you are not concerned about forwarding cancellation notifications to lower invocations, you can either: @@ -144,19 +144,19 @@ If you are not concerned about forwarding cancellation notifications to lower in Explicitly pass `default`: ```csharp - public static void MyMethod(CancellationToken c) - { - MyMethodWithOverload(default); - } +public static void MyMethod(CancellationToken ct) +{ + MyMethodWithOverload(default); +} ``` Or explicitly pass `CancellationToken.None`: ```csharp - public static void MyMethod(CancellationToken c) - { - MyMethodWithOverload(CancellationToken.None); - } +public static void MyMethod(CancellationToken ct) +{ + MyMethodWithOverload(CancellationToken.None); +} ``` ## Non-violation examples @@ -174,7 +174,7 @@ namespace ConsoleApp { } - public static void MyMethod(CancellationToken c, int lastParameter) + public static void MyMethod(CancellationToken ct, int lastParameter) { MyMethodWithDefault(); } @@ -195,7 +195,7 @@ namespace ConsoleApp { } - public static void MyMethod(CancellationToken c) + public static void MyMethod(CancellationToken ct) { MyMethodWithDefault(); } @@ -219,7 +219,7 @@ namespace ConsoleApp { } - public static void MyMethod(CancellationToken c) + public static void MyMethod(CancellationToken ct) { MyMethodWithOverload(); } @@ -240,7 +240,7 @@ namespace ConsoleApp { } - public static void MyMethod(CancellationToken c1, CancellationToken c2) + public static void MyMethod(CancellationToken ct1, CancellationToken ct2) { MyMethodWithDefault(); } @@ -257,11 +257,11 @@ namespace ConsoleApp { public static class MyTestClass { - public static void MyMethodWithDefault(CancellationToken c1 = default, CancellationToken c2 = default) + public static void MyMethodWithDefault(CancellationToken ct1 = default, CancellationToken ct2 = default) { } - public static void MyMethod(CancellationToken c) + public static void MyMethod(CancellationToken ct) { MyMethodWithDefault(); } @@ -278,7 +278,7 @@ namespace ConsoleApp { public static class MyTestClass { - public static void MyMethodWithOverload(CancellationToken c1, CancellationToken c2) + public static void MyMethodWithOverload(CancellationToken ct1, CancellationToken ct2) { } @@ -286,7 +286,7 @@ namespace ConsoleApp { } - public static void MyMethod(CancellationToken c) + public static void MyMethod(CancellationToken ct) { MyMethodWithOverload(); } diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2201.md b/docs/fundamentals/code-analysis/quality-rules/ca2201.md index d9318688aa6ab..4cd040f6adabf 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca2201.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca2201.md @@ -10,6 +10,8 @@ helpviewer_keywords: - DoNotRaiseReservedExceptionTypes author: gewarren ms.author: gewarren +dev_langs: +- CSharp --- # CA2201: Do not raise reserved exception types @@ -78,6 +80,29 @@ For all other situations, consider creating your own type that derives from enum value with the corresponding enum value. ```csharp - // Violation - var tcs = new TaskCompletionSource(TaskContinuationOptions.RunContinuationsAsynchronously); +// Violation +var tcs = new TaskCompletionSource(TaskContinuationOptions.RunContinuationsAsynchronously); - // Fixed - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); +// Fixed +var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); ``` ## When to suppress warnings diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2251.md b/docs/fundamentals/code-analysis/quality-rules/ca2251.md index bda71465dac68..8e0c270a09ef4 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca2251.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca2251.md @@ -32,6 +32,19 @@ The result of a call to with a call to . +## Example + +```csharp +string leftValue = "..."; +string rightValue = "..."; + +// This code violates the rule. +bool areEqualUsingCompare = string.Compare(leftValue, rightValue, StringComparison.OrdinalIgnoreCase) == 0; + +// This code satisfies the rule. +bool areEqualUsingEquals = string.Equals(leftValue, rightValue, StringComparison.OrdinalIgnoreCase); +``` + ## When to suppress warnings It is safe to suppress warnings from this rule. diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2253.md b/docs/fundamentals/code-analysis/quality-rules/ca2253.md index 300148f1e004d..65d4540c7d579 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca2253.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca2253.md @@ -9,6 +9,8 @@ helpviewer_keywords: - LoggerMessageDefineAnalyzer - CA2253 author: Youssef1313 +dev_langs: +- CSharp --- # CA2253: Named placeholders should not be numeric values @@ -34,6 +36,10 @@ Rename the numeric placeholder. For usage examples, see the method. +## Example + +:::code language="csharp" source="snippets/csharp/all-rules/ca2253.cs" id="snippet1"::: + ## When to suppress errors Do not suppress a warning from this rule. diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2256.md b/docs/fundamentals/code-analysis/quality-rules/ca2256.md index 141b1597ee659..d6b2ec326839a 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca2256.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca2256.md @@ -9,6 +9,8 @@ helpviewer_keywords: - DynamicInterfaceCastableImplementationAnalyzer - CA2256 author: Youssef1313 +dev_langs: +- CSharp --- # CA2256: All members declared in parent interfaces must have an implementation in a DynamicInterfaceCastableImplementation-attributed interface @@ -32,6 +34,10 @@ Types attributed with + // This code violates the rule. + public class Short + { + public int Int32 { get; set; } + public Guid Guid { get; set; } + + public void Float(int int32) { } + } + // +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1725.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1725.cs new file mode 100644 index 0000000000000..14b35389a530a --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1725.cs @@ -0,0 +1,21 @@ +using System; + +namespace ca1725 +{ + // + public interface IUserService + { + int GetAge(int id); + } + + public class UserService : IUserService + { + // Violates CA1725: Parameter name should match the base declaration ('id') + // for consistency with IUserService + public int GetAge(int userId) + { + throw new NotImplementedException(); + } + } + // +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1727.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1727.cs new file mode 100644 index 0000000000000..45666b3429214 --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1727.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; + +namespace ca1727 +{ + // + public class UserService + { + private readonly ILogger _logger; + + public UserService(ILogger logger) + { + _logger = logger; + } + + public void Create(string firstName, string lastName) + { + // This code violates the rule. + _logger.LogInformation("Creating user {firstName} {lastName}", firstName, lastName); + + // This code satisfies the rule. + _logger.LogInformation("Creating user {FirstName} {LastName}", firstName, lastName); + } + } + // +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1822.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1822.cs new file mode 100644 index 0000000000000..c0f81578b44e7 --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1822.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace ca1822 +{ + // + public class Printer + { + private readonly List _items = [ + 'H', 'e', 'l', 'l', 'o', + ]; + + public void PrintHello() + { + BadPrintHelloInternal(); + GoodPrintHelloInternal(); + GoodPrintHelloStaticInternal(); + } + + // This method violates the rule. + private void BadPrintHelloInternal() + { + Console.WriteLine("Hello"); + } + + // This methods satisfies the rule. + private void GoodPrintHelloInternal() + { + Console.WriteLine(string.Join(string.Empty, this._items)); + } + + private static void GoodPrintHelloStaticInternal() + { + Console.WriteLine("Hello"); + } + } + // +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1823.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1823.cs new file mode 100644 index 0000000000000..255d7d13a5766 --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1823.cs @@ -0,0 +1,24 @@ +namespace ca1823 +{ + // + public class User + { + private readonly string _firstName; + private readonly string _lastName; + + // CA1823: Unused field '_age' + private readonly int _age; + + public User(string firstName, string lastName) + { + _firstName = firstName; + _lastName = lastName; + } + + public string GetFullName() + { + return $"My name is {_firstName} {_lastName}"; + } + } + // +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2012.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2012.cs new file mode 100644 index 0000000000000..7e27fc35ea61e --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2012.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; + +namespace ca2012 +{ + // + public class NumberValueTask + { + public async ValueTask GetNumberAsync() + { + await Task.Delay(100); + return 123; + } + + public async Task UseValueTaskIncorrectlyAsync() + { + // This code violates the rule, + // because ValueTask is awaited multiple times + ValueTask numberValueTask = GetNumberAsync(); + + int first = await numberValueTask; + int second = await numberValueTask; // <- illegal reuse + + // ... + } + + // This code satisfies the rule. + public async Task UseValueTaskCorrectlyAsync() + { + int first = await GetNumberAsync(); + int second = await GetNumberAsync(); + + // .. + } + + public async Task UseValueTaskAsTaskAsync() + { + ValueTask numberValueTask = GetNumberAsync(); + + Task numberTask = numberValueTask.AsTask(); + + int first = await numberTask; + int second = await numberTask; + + // ... + } + } + // +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2014.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2014.cs new file mode 100644 index 0000000000000..ae670449897ab --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2014.cs @@ -0,0 +1,36 @@ +using System; + +namespace ca2014 +{ + public class Example + { + // + // This method violates the rule. + public void ProcessDataBad() + { + for (int i = 0; i < 100; i++) + { + // CA2014: Potential stack overflow. + // Move the stackalloc out of the loop. + Span buffer = stackalloc int[100]; + buffer[0] = i; + + // ... + } + } + + // This method satisfies the rule. + public void ProcessDataGood() + { + Span buffer = stackalloc int[100]; + + for (int i = 0; i < 100; i++) + { + buffer[0] = i; + + // ... + } + } + // + } +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2207.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2207.cs new file mode 100644 index 0000000000000..54346031ba154 --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2207.cs @@ -0,0 +1,28 @@ +namespace ca2207 +{ + // + // This struct violates the rule. + struct BadStruct + { + private static readonly int s_first; + private static readonly int s_second; + + static BadStruct() + { + s_first = 1; + s_second = 2; + } + + // ... + } + + // This struct satisfies the rule. + struct GoodStruct + { + private static readonly int s_first = 1; + private static readonly int s_second = 2; + + // ... + } + // +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2253.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2253.cs new file mode 100644 index 0000000000000..4964dbf5f9c72 --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2253.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.Logging; + +namespace ca2253 +{ + // + public class UserService + { + private readonly ILogger _logger; + + public UserService(ILogger logger) + { + _logger = logger; + } + + public void Add(string firstName, string lastName) + { + // This code violates the rule. + _logger.LogInformation("Adding user with first name {0} and last name {1}", firstName, lastName); + + // This code satisfies the rule. + _logger.LogInformation("Adding user with first name {FirstName} and last name {LastName}", firstName, lastName); + + // ... + } + } + // +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2256.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2256.cs new file mode 100644 index 0000000000000..8c59cb6794dd1 --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2256.cs @@ -0,0 +1,36 @@ +using System.Runtime.InteropServices; + +namespace ca2256 +{ + // + interface IParent + { + void ParentMethod(); + } + + // This interface violates the rule. + [DynamicInterfaceCastableImplementation] + interface IBadChild : IParent + { + static void ChildMethod() + { + // ... + } + } + + // This interface satisfies the rule. + [DynamicInterfaceCastableImplementation] + interface IGoodChild : IParent + { + static void ChildMethod() + { + // ... + } + + void IParent.ParentMethod() + { + // ... + } + } + // +} diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2257.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2257.cs new file mode 100644 index 0000000000000..076dd90adad9f --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2257.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace ca2257 +{ + // + [DynamicInterfaceCastableImplementation] + interface IExample + { + // This method violates the rule. + void BadMethod(); + + // This method satisfies the rule. + static void GoodMethod() + { + // ... + } + } + // +}