|
1 | 1 | <p>This rule raises an issue when code uses 'field' as an identifier in contexts where it conflicts with the new <code>field</code> contextual keyword |
2 | 2 | introduced in C# 14.</p> |
3 | 3 | <h2>Why is this an issue?</h2> |
4 | | -<p>C# 14 introduces the <code>field</code> contextual keyword for field-backed properties. This keyword allows you to access synthesized backing |
| 4 | +<p>C# 14 introduces the <code>field</code> contextual keyword for field-backed properties. This keyword allows access to the synthesized backing |
5 | 5 | fields directly within property accessors, simplifying property implementations that need custom logic.</p> |
6 | | -<p>When your code uses 'field' as an identifier, several problems can occur:</p> |
| 6 | +<p>By using 'field' as an identifier, several problems can occur:</p> |
7 | 7 | <ul> |
8 | | - <li><strong>Compilation errors</strong>: Local variables or parameters named 'field' within property accessors will cause compiler error CS9272, |
9 | | - preventing your code from compiling.</li> |
10 | | - <li><strong>Semantic confusion</strong>: Existing class members named 'field' may be overshadowed by the synthesized backing field when referenced |
11 | | - within property accessors, leading to unexpected behavior.</li> |
12 | | - <li><strong>Upgrade barriers</strong>: Code that compiles in earlier C# versions may break when upgrading to C# 14.</li> |
| 8 | + <li><strong>Compilation errors</strong>: Local variable declarations or parameters named <code>field</code> within property accessors cause compiler |
| 9 | + error CS9273. References to existing members named <code>field</code> within property accessors cause compiler error CS9258. See <a |
| 10 | + href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors">Compiler errors on property |
| 11 | + declarations</a>.</li> |
| 12 | + <li><strong>Semantic confusion</strong>: Existing class members named <code>field</code> may be unexpectedly overshadowed by the synthesized backing |
| 13 | + field when referenced within property accessors, leading to logic errors and unexpected runtime behavior.</li> |
| 14 | + <li><strong>Upgrade barriers</strong>: Code that compiles successfully in C# 13 and earlier may fail to compile or change behavior when upgrading to |
| 15 | + C# 14.</li> |
13 | 16 | </ul> |
14 | | -<p>The <code>field</code> keyword specifically refers to compiler-synthesized backing fields for properties. When the compiler encounters 'field' |
15 | | -within a property accessor, it treats it as this special keyword rather than a regular identifier, which can cause conflicts with your existing |
16 | | -code.</p> |
17 | 17 | <h3>What is the potential impact?</h3> |
18 | | -<p>Using 'field' as an identifier can prevent successful compilation when upgrading to C# 14. In property accessors, local variables named 'field' |
19 | | -will cause compilation errors, while class members named 'field' may be unexpectedly overshadowed by synthesized backing fields, leading to logic |
20 | | -errors and unexpected runtime behavior.</p> |
| 18 | +<p>Using 'field' as an identifier can prevent successful compilation when upgrading to C# 14. In property accessors, local variables or parameters |
| 19 | +named 'field' will cause compilation errors, while class members named 'field' may be unexpectedly overshadowed by synthesized backing fields, leading |
| 20 | +to logic errors and unexpected runtime behavior.</p> |
21 | 21 | <h2>How to fix it</h2> |
22 | | -<p>Rename class members that use 'field' as an identifier to avoid conflicts with the contextual keyword, or escape the field identifier with "@".</p> |
| 22 | +<p>Rename the identifier, escape it by prefixing with <code>@</code>, or qualify member access with <code>this.</code> or <code>base.</code> to avoid |
| 23 | +conflicts with the contextual keyword. This rule applies only inside property <code>get</code>, <code>set</code>, and <code>init</code> accessors; |
| 24 | +indexer and event accessors are not affected.</p> |
23 | 25 | <h3>Code examples</h3> |
24 | 26 | <h4>Noncompliant code example</h4> |
25 | 27 | <pre data-diff-id="1" data-diff-type="noncompliant"> |
26 | | -public class MyClass |
| 28 | +public class ClassFieldExample |
27 | 29 | { |
28 | | - private string field; // Noncompliant |
| 30 | + private string field; |
29 | 31 |
|
30 | 32 | public string Message |
31 | 33 | { |
32 | | - get => field; |
33 | | - set => field = value; |
| 34 | + get => field; // Noncompliant |
| 35 | + set => field = value; // Noncompliant |
34 | 36 | } |
35 | 37 | } |
36 | | - |
37 | | -public class MyClass2 |
| 38 | +</pre> |
| 39 | +<pre data-diff-id="2" data-diff-type="noncompliant"> |
| 40 | +public class LocalFunctionExample |
38 | 41 | { |
39 | | - private string field; // Noncompliant |
40 | | - |
41 | | - public string Message |
| 42 | + public int Value |
42 | 43 | { |
43 | | - get => field; |
44 | | - set => field = value; |
| 44 | + get |
| 45 | + { |
| 46 | + return LocalFunction(42); |
| 47 | + |
| 48 | + int LocalFunction(int field) // Noncompliant |
| 49 | + => field; |
| 50 | + } |
45 | 51 | } |
46 | 52 | } |
47 | 53 | </pre> |
48 | 54 | <h4>Compliant solution</h4> |
49 | 55 | <pre data-diff-id="1" data-diff-type="compliant"> |
50 | | -public class MyClass |
| 56 | +public class ClassFieldExample |
51 | 57 | { |
52 | | - private string _field; |
| 58 | + private string field; |
53 | 59 |
|
54 | 60 | public string Message |
55 | 61 | { |
56 | | - get => _field; |
57 | | - set => _field = value; |
| 62 | + get => this.field; // or @field |
| 63 | + set => this.field = value; // or @field = value; |
58 | 64 | } |
59 | 65 | } |
60 | | - |
61 | | -public class MyClass2 |
| 66 | +</pre> |
| 67 | +<pre data-diff-id="2" data-diff-type="compliant"> |
| 68 | +public class LocalFunctionExample |
62 | 69 | { |
63 | | - private string field; |
64 | | - |
65 | | - public string Message |
| 70 | + public int Value |
66 | 71 | { |
67 | | - get => @field; |
68 | | - set => @field = value; |
| 72 | + get |
| 73 | + { |
| 74 | + return LocalFunction(42); |
| 75 | + |
| 76 | + int LocalFunction(int value) // Compliant - renamed |
| 77 | + => value; |
| 78 | + } |
69 | 79 | } |
70 | 80 | } |
71 | 81 | </pre> |
72 | 82 | <h2>Resources</h2> |
73 | 83 | <h3>Documentation</h3> |
74 | 84 | <ul> |
75 | | - <li>What’s new in C# 14 - The field keyword - <a |
76 | | - href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14#the-field-keyword">Official Microsoft documentation explaining the field |
77 | | - keyword feature in C# 14</a></li> |
78 | | - <li>Breaking changes in Roslyn - field keyword conflicts - <a |
79 | | - href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/breaking-changes/compiler%20breaking%20changes%20-%20dotnet%2010">Documentation of |
80 | | - breaking changes related to the field keyword in C# 14</a></li> |
| 85 | + <li>Microsoft Learn - <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/field">The <code>field</code> |
| 86 | + keyword</a></li> |
| 87 | + <li>Microsoft Learn - <a |
| 88 | + href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors">Compiler errors on property |
| 89 | + declarations</a></li> |
| 90 | + <li>Microsoft Learn - <a |
| 91 | + href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/breaking-changes/compiler%20breaking%20changes%20-%20dotnet%2010#expression-field-in-a-property-accessor-refers-to-synthesized-backing-field">C# compiler breaking changes since C# 13 - Expression <code>field</code> in a property accessor refers to synthesized backing field</a></li> |
| 92 | + <li>Microsoft Learn - <a |
| 93 | + href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/breaking-changes/compiler%20breaking%20changes%20-%20dotnet%2010#variable-named-field-disallowed-in-a-property-accessor">C# compiler breaking changes since C# 13 - Variable named <code>field</code> disallowed in a property accessor</a> (documentation incorrectly references CS9272; the actual error code is CS9273)</li> |
81 | 94 | </ul> |
82 | 95 |
|
0 commit comments