Unassigned Readonly Field
ID |
csharp.unassigned_readonly_field |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
CSharp |
Tags |
field, reliability |
Description
Reports readonly fields that have neither an inline initializer nor an assignment in
any constructor of the enclosing type. Such fields are silently left at the type’s
default value (zero, false, or null).
Rationale
readonly advertises that the value is set once and never mutated again. If no
initialisation runs, every consumer reads the default value, which usually leads to
`NullReferenceException`s or subtle wrong-default bugs. The compiler will not complain
because a missing assignment is a valid program, but it is almost never the developer’s
intent.
public class Account
{
private readonly string _id; // FLAW — never assigned
private readonly DateTime _created; // FLAW
public Account()
{
// forgot to assign _id and _created
}
}
public class AccountOk
{
private readonly string _id = Guid.NewGuid().ToString(); // OK
private readonly DateTime _created;
public AccountOk(DateTime created)
{
_created = created; // OK
}
}
public class ExpressionBodiedOk
{
private readonly int _value; // OK — assigned by the ctor's whole body
public ExpressionBodiedOk(int value) => _value = value;
}
public class TupleDeconstructedOk
{
private readonly int _a; // OK
private readonly int _b; // OK
public TupleDeconstructedOk()
{
(_a, _b) = ComputePair(); // both assigned via deconstruction
}
private static (int, int) ComputePair() => (1, 2);
}
Two assignment shapes are recognised alongside the plain field = value; and
this.field = value; forms: an expression-bodied constructor whose entire body is the
assignment (⇒ field = value;), and a tuple-deconstruction assignment where the field is
one of the targets ((field1, field2) = expr;).
Remediation
Assign the field either inline at the declaration or unconditionally in every
constructor. If the value cannot be known until after construction, the field probably
should not be readonly.