Skip to content

Commit 0e2035c

Browse files
Merge pull request #49423 from dotnet/main
Merge main into live
2 parents 4a1515f + 4b1fdf5 commit 0e2035c

File tree

32 files changed

+624
-42
lines changed

32 files changed

+624
-42
lines changed

docs/core/compatibility/10.0.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af
130130
| [NUGET_ENABLE_ENHANCED_HTTP_RETRY environment variable removed](sdk/10.0/nuget-enhanced-http-retry-removed.md) | Behavioral change | Preview 6 |
131131
| [NuGet logs an error for invalid package IDs](sdk/10.0/nuget-packageid-validation.md) | Behavioral change | RC 1 |
132132

133+
## Serialization
134+
135+
| Title | Type of change | Introduced version |
136+
|-------|-------------------|--------------------|
137+
| [XmlSerializer no longer ignores properties marked with ObsoleteAttribute](serialization/10/xmlserializer-obsolete-properties.md) | Behavioral change | Preview 1 |
138+
133139
## Windows Forms
134140

135141
| Title | Type of change | Introduced version |
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
---
2+
title: "Breaking change: XmlSerializer no longer ignores properties marked with ObsoleteAttribute"
3+
description: "Learn about the breaking change in .NET 10 where properties marked with ObsoleteAttribute are now serialized by XmlSerializer instead of being ignored."
4+
ms.date: 10/21/2025
5+
ai-usage: ai-assisted
6+
ms.custom: https://github.com/dotnet/docs/issues/49054
7+
---
8+
# XmlSerializer no longer ignores properties marked with ObsoleteAttribute
9+
10+
Starting in .NET 10, the behavior of <xref:System.Xml.Serialization.XmlSerializer> has changed with respect to how it handles properties marked with the <xref:System.ObsoleteAttribute> 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.
11+
12+
With this change, properties marked with `[Obsolete]` are now serialized by default unless the <xref:System.ObsoleteAttribute.IsError> property is set to `true`. If `IsError` is `true`, the serializer throws an <xref:System.InvalidOperationException> during creation. Additionally, an AppContext switch, `Switch.System.Xml.IgnoreObsoleteMembers`, has been introduced to allow developers to revert to the previous behavior, if necessary.
13+
14+
## Version introduced
15+
16+
.NET 10 Preview 1
17+
18+
## Previous behavior
19+
20+
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.
21+
22+
```csharp
23+
public class Example
24+
{
25+
public string NormalProperty { get; set; } = "normal";
26+
27+
[Obsolete("This property is deprecated")]
28+
public string ObsoleteProperty { get; set; } = "obsolete";
29+
30+
[XmlIgnore]
31+
public string IgnoredProperty { get; set; } = "ignored";
32+
}
33+
34+
var obj = new Example();
35+
var serializer = new XmlSerializer(typeof(Example));
36+
using var writer = new StringWriter();
37+
serializer.Serialize(writer, obj);
38+
Console.WriteLine(writer.ToString());
39+
```
40+
41+
**Output before the change:**
42+
43+
```xml
44+
<Example>
45+
<NormalProperty>normal</NormalProperty>
46+
</Example>
47+
```
48+
49+
## New behavior
50+
51+
Starting in .NET 10, properties marked with `[Obsolete]` are no longer excluded from XML serialization by default. Instead:
52+
53+
- If the `[Obsolete]` attribute is applied with `IsError = false` (default), the property is serialized normally.
54+
- If the `[Obsolete]` attribute is applied with `IsError = true`, the <xref:System.Xml.Serialization.XmlSerializer> throws an <xref:System.InvalidOperationException> during serializer creation.
55+
56+
Using the same code as shown in the previous behavior section, the output after the change is:
57+
58+
```xml
59+
<Example>
60+
<NormalProperty>normal</NormalProperty>
61+
<ObsoleteProperty>obsolete</ObsoleteProperty>
62+
</Example>
63+
```
64+
65+
If `[Obsolete(IsError = true)]` is applied to a property, the following exception is thrown during serializer creation:
66+
67+
> System.InvalidOperationException: Cannot serialize member 'ObsoleteProperty' because it is marked with ObsoleteAttribute and IsError is set to true.
68+
69+
> [!NOTE]
70+
> 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."
71+
72+
## Type of breaking change
73+
74+
This change is a [behavioral change](../../categories.md#behavioral-change).
75+
76+
## Reason for change
77+
78+
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.
79+
80+
## Recommended action
81+
82+
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:
83+
84+
```csharp
85+
AppContext.SetSwitch("Switch.System.Xml.IgnoreObsoleteMembers", true);
86+
```
87+
88+
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.
89+
90+
## Affected APIs
91+
92+
- <xref:System.Xml.Serialization.XmlSerializer?displayProperty=fullName>

docs/core/compatibility/toc.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ items:
162162
href: sdk/10.0/prune-packagereference-privateassets.md
163163
- name: Version requirements for .NET 10 SDK
164164
href: sdk/10.0/version-requirements.md
165+
- name: Serialization
166+
items:
167+
- name: XmlSerializer no longer ignores properties marked with ObsoleteAttribute
168+
href: serialization/10/xmlserializer-obsolete-properties.md
165169
- name: Windows Forms
166170
items:
167171
- name: API obsoletions

docs/fundamentals/code-analysis/quality-rules/ca1720.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ helpviewer_keywords:
1010
- CA1720
1111
author: gewarren
1212
ms.author: gewarren
13+
dev_langs:
14+
- CSharp
1315
---
1416
# CA1720: Identifiers should not contain type names
1517

@@ -91,6 +93,10 @@ Replace the data type identifier in the name of the parameter with either a term
9193

9294
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'.
9395

96+
## Example
97+
98+
:::code language="csharp" source="snippets/csharp/all-rules/ca1720.cs" id="snippet1":::
99+
94100
## When to suppress warnings
95101

96102
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.

docs/fundamentals/code-analysis/quality-rules/ca1725.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ helpviewer_keywords:
1010
- ParameterNamesShouldMatchBaseDeclaration
1111
author: gewarren
1212
ms.author: gewarren
13+
dev_langs:
14+
- CSharp
1315
---
1416
# CA1725: Parameter names should match base declaration
1517

@@ -35,6 +37,10 @@ Consistent naming of parameters in an override hierarchy increases the usability
3537

3638
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.
3739

40+
## Example
41+
42+
:::code language="csharp" source="snippets/csharp/all-rules/ca1725.cs" id="snippet1":::
43+
3844
## When to suppress warnings
3945

4046
Do not suppress a warning from this rule except for visible methods in libraries that have previously shipped.

docs/fundamentals/code-analysis/quality-rules/ca1727.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ helpviewer_keywords:
99
- CA1727
1010
- LoggerMessageDefineAnalyzer
1111
author: Youssef1313
12+
dev_langs:
13+
- CSharp
1214
---
1315
# CA1727: Use PascalCase for named placeholders
1416

@@ -32,6 +34,10 @@ A named placeholder used with <xref:Microsoft.Extensions.Logging.ILogger> should
3234

3335
Use PascalCase for named placeholders. For example, change `{firstName}` to `{FirstName}`.
3436

37+
## Example
38+
39+
:::code language="csharp" source="snippets/csharp/all-rules/ca1727.cs" id="snippet1":::
40+
3541
## When to suppress warnings
3642

3743
It is safe to suppress a warning from this rule.

docs/fundamentals/code-analysis/quality-rules/ca1822.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ helpviewer_keywords:
1010
- CA1822
1111
author: gewarren
1212
ms.author: gewarren
13+
dev_langs:
14+
- CSharp
1315
---
1416
# CA1822: Mark members as static
1517

@@ -33,6 +35,10 @@ Members that do not access instance data or call instance methods can be marked
3335

3436
Mark the member as static (or Shared in Visual Basic) or use 'this'/'Me' in the method body, if appropriate.
3537

38+
## Example
39+
40+
:::code language="csharp" source="snippets/csharp/all-rules/ca1822.cs" id="snippet1":::
41+
3642
## When to suppress warnings
3743

3844
It is safe to suppress a warning from this rule for previously shipped code for which the fix would be a breaking change.

docs/fundamentals/code-analysis/quality-rules/ca1823.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ helpviewer_keywords:
1010
- CA1823
1111
author: gewarren
1212
ms.author: gewarren
13+
dev_langs:
14+
- CSharp
1315
---
1416
# CA1823: Avoid unused private fields
1517

@@ -33,6 +35,10 @@ Private fields were detected that do not appear to be accessed in the assembly.
3335

3436
To fix a violation of this rule, remove the field or add code that uses it.
3537

38+
## Example
39+
40+
:::code language="csharp" source="snippets/csharp/all-rules/ca1823.cs" id="snippet1":::
41+
3642
## When to suppress warnings
3743

3844
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
6066

6167
- [CA1812: Avoid uninstantiated internal classes](ca1812.md)
6268
- [CA1801: Review unused parameters](ca1801.md)
69+
- [Remove unread private member (IDE0052)](../style-rules/ide0052.md)

docs/fundamentals/code-analysis/quality-rules/ca2008.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ helpviewer_keywords:
99
- CA2008
1010
author: gewarren
1111
ms.author: gewarren
12+
dev_langs:
13+
- CSharp
1214
---
1315
# CA2008: Do not create tasks without passing a TaskScheduler
1416

@@ -42,6 +44,44 @@ For further information and detailed examples, see [New TaskCreationOptions and
4244

4345
To fix violations, call the method overload that takes a <xref:System.Threading.Tasks.TaskScheduler> and explicitly pass in <xref:System.Threading.Tasks.TaskScheduler.Default%2A> or <xref:System.Threading.Tasks.TaskScheduler.Current%2A> to make the intent clear.
4446

47+
## Example
48+
49+
```csharp
50+
// This code violates the rule.
51+
var badTask = Task.Factory.StartNew(
52+
() =>
53+
{
54+
// ...
55+
}
56+
);
57+
badTask.ContinueWith(
58+
t =>
59+
{
60+
// ...
61+
}
62+
);
63+
64+
// This code satisfies the rule.
65+
var goodTask = Task.Factory.StartNew(
66+
() =>
67+
{
68+
// ...
69+
},
70+
CancellationToken.None,
71+
TaskCreationOptions.None,
72+
TaskScheduler.Default
73+
);
74+
goodTask.ContinueWith(
75+
t =>
76+
{
77+
// ...
78+
},
79+
CancellationToken.None,
80+
TaskContinuationOptions.None,
81+
TaskScheduler.Default
82+
);
83+
```
84+
4585
## When to suppress warnings
4686

4787
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.

docs/fundamentals/code-analysis/quality-rules/ca2012.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ helpviewer_keywords:
1010
- "CA2012"
1111
author: stephentoub
1212
ms.author: stoub
13+
dev_langs:
14+
- CSharp
1315
---
1416
# CA2012: Use ValueTasks correctly
1517

@@ -37,6 +39,10 @@ In general, ValueTasks should be directly awaited rather than discarded or store
3739

3840
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 <xref:System.Threading.Tasks.Task> object.
3941

42+
## Example
43+
44+
:::code language="csharp" source="snippets/csharp/all-rules/ca2012.cs" id="snippet1":::
45+
4046
## Suppress a warning
4147

4248
If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.

0 commit comments

Comments
 (0)