Avoid static fields with a mutable field type

Rule ND1902 Immutability

Warns about static fields with a mutable field type: they hold modifiable state. Instance fields are the natural OOP artifact for mutable state; such static fields create confusion about runtime state. More: https://blog.ndepend.com/the-proper-usages-of-the-keyword-static-in-c/

How to fix

Hold mutable states in objects passed explicitly wherever consumed, rather than in a static field modifiable from everywhere in the program.

CQLinq source

This rule is written in CQLinq, C# LINQ over the NDepend code model. It ships with every new NDepend project: you can read it, adapt it, or use it as a starting point for your own custom rules.

// <Name>Avoid static fields with a mutable field type</Name>
// <Id>ND1902:AvoidStaticFieldsWithAMutableFieldType</Id>

warnif count > 0
from f in Application.Fields
where f.IsStatic && 
     !f.IsEnumValue && 
     !f.IsGeneratedByCompiler &&
     !f.IsLiteral

let fieldType = f.FieldType
where fieldType != null && 
     !fieldType.IsThirdParty && 
     !fieldType.IsInterface && 
     !fieldType.IsDelegate &&
     !fieldType.IsImmutable
     
select new { 
   f, 
   mutableFieldType = fieldType , 
   isFieldImmutable = f.IsImmutable ? "Immutable" : "Mutable", 
   isFieldReadOnly = f.IsInitOnly ? "ReadOnly" : "Not ReadOnly",
   Debt = 10.ToMinutes().ToDebt(),
   Severity = Severity.Medium
}

//<Expl>
// The *static {0}* is typed with the *{1}* that is mutable: its states can be modified at runtime.
// This can lead to runtime confusion and hinder code testability.
// In *Object-Oriented Programming*, *instance fields* are the preferred choice for holding modifiable states.
//</Expl>


//<Desc>
// Warns about static fields with a mutable field type: they hold modifiable
// state. **Instance fields** are the natural OOP artifact for mutable state;
// such static fields create *confusion* about runtime state. More:
// https://blog.ndepend.com/the-proper-usages-of-the-keyword-static-in-c/
//</Desc>

//<HowToFix>
// Hold mutable states in objects passed **explicitly** wherever consumed,
// rather than in a static field modifiable from everywhere in the program.
//</HowToFix>

Immutability: all 15 items