HLQ011: Mutable value-type enumerators cannot be stored in a 'readonly' field.
July 17, 2023 ยท View on GitHub
Cause
A mutable value-type enumerators is being stored in a 'readonly' field.
Severity
Error
Rule description
Enumerators are usually mutable. They have to store the state so that, when MoveNext() is called, it moves to the next item, if available.
A rare example of an immutable enumerator is the one generated by System.Linq.Enumerable.Empty(). Its MoveNext() method implementation returns always false.
When the enumerator is a value type, this is particularly important. If the enumerator is stored in a readonly field, when MoveNext() is called, a copy of the enumerator is made and the state changed on this other one.
If the enumerator is a value type but not mutable, it should be declared as readonly struct. In this case, the copy will not be made.
How to fix violations
Either remove the readonly keyword from the field or, if possible, add the readonly keyword to the enumerator definition.
NOTE: When the readonly is removed from the field, you may get an IDE0044 warning, telling you to add it back. Disable this rule for this line.
When to suppress warnings
Should not be suppressed.
Example of a violation
class Enumerator<T>
{
readonly MutableEnumerator source; // readonly field
public Enumerator(MutableEnumerator source)
=> this.source = source;
}
class Enumerator<TEnumerator> where TEnumerator : struct, IEnumerator
{
readonly TEnumerator source; // readonly field
public Enumerator(TEnumerator source)
=> this.source = source;
}
Example of how to fix
class Enumerator<T>
{
[SuppressMessage("Style", "IDE0044:Add readonly modifier")]
MutableEnumerator source; // readonly removed
public Enumerator(MutableEnumerator source)
=> this.source = source;
}
class Enumerator<TEnumerator> where TEnumerator : struct, IEnumerator
{
[SuppressMessage("Style", "IDE0044:Add readonly modifier")]
TEnumerator source; // readonly removed
public Enumerator(TEnumerator source)
=> this.source = source;
}