Skip to content

Commit aae38d8

Browse files
CopilotBillWagner
andauthored
[WIP] Why CS0236 (#47119)
* Initial plan * Enhance CS0236 documentation with explanation of why the error occurs Co-authored-by: BillWagner <[email protected]> * Fix CS0236 documentation inaccuracies about field initialization order and rule purpose Co-authored-by: BillWagner <[email protected]> * Change 'class constructor' to 'instance constructor' for more precise terminology Co-authored-by: BillWagner <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: BillWagner <[email protected]>
1 parent aebc8c6 commit aae38d8

File tree

1 file changed

+56
-4
lines changed

1 file changed

+56
-4
lines changed

docs/csharp/misc/cs0236.md

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,27 @@ A field initializer cannot reference the non-static field, method, or property '
1313

1414
Instance fields cannot be used to initialize other instance fields outside a method.
1515

16+
## Why this error occurs
17+
18+
The compiler enforces this restriction because of how object initialization works in C#. When an object is created, field initializers are processed before any constructor code runs. During this phase:
19+
20+
1. **Field dependency restriction**: While field initializers are processed in lexical order within a single file, the rule prevents dependencies between fields to allow class authors to rearrange fields without introducing compiler errors. For partial classes, the order of field initializers across different source files isn't specified.
21+
22+
2. **Object is not fully constructed**: When field initializers run, the object instance is in an incomplete state. Allowing references between fields during this phase could lead to accessing uninitialized memory or unpredictable behavior.
23+
24+
3. **Compiler safety**: This restriction prevents potential runtime errors and ensures predictable object construction behavior.
25+
26+
The compiler detects this pattern during compilation and reports CS0236 to prevent these potential issues.
27+
1628
## To correct this error
1729

18-
If you are trying to initialize a variable outside a method, consider performing the initialization inside the class constructor. For more information, see [Methods](../programming-guide/classes-and-structs/methods.md).
30+
1. **Move initialization to constructor**: Perform the initialization inside an instance constructor where all fields are guaranteed to be available.
31+
32+
2. **Use static fields**: If the referenced field doesn't need to be instance-specific, consider making it static.
33+
34+
3. **Use default values**: Initialize fields with literal values or expressions that don't reference other instance members.
35+
36+
4. **Lazy initialization**: Use properties with backing fields for complex initialization logic that depends on other instance members.
1937

2038
## Example
2139

@@ -26,13 +44,47 @@ public class MyClass
2644
{
2745
public int i = 5;
2846

29-
// To fix the error, remove "= i", and uncomment the line in constructor.
47+
// CS0236: Field initializer cannot reference instance field 'i'
48+
// This restriction allows class authors to rearrange fields without compiler errors
3049
public int j = i; // CS0236
3150
3251
public MyClass()
3352
{
34-
// Uncomment the following.
35-
//j = i;
53+
// This works because both fields are guaranteed to be initialized
54+
// before constructor code runs
55+
j = i;
56+
}
57+
}
58+
```
59+
60+
## Additional examples
61+
62+
The following examples demonstrate different scenarios where CS0236 occurs:
63+
64+
```csharp
65+
public class Examples
66+
{
67+
private string name = "Default";
68+
69+
// CS0236: Cannot reference instance field in initializer
70+
private string displayName = name.ToUpper();
71+
72+
// CS0236: Cannot reference instance method in initializer
73+
private int length = GetNameLength();
74+
75+
// CS0236: Cannot reference instance property in initializer
76+
private string formatted = FormattedName;
77+
78+
public string FormattedName => $"Name: {name}";
79+
80+
private int GetNameLength() => name.Length;
81+
82+
public Examples()
83+
{
84+
// All of these work in the constructor:
85+
displayName = name.ToUpper();
86+
length = GetNameLength();
87+
formatted = FormattedName;
3688
}
3789
}
3890
```

0 commit comments

Comments
 (0)