A field must not be assigned from outside its parent hierarchy types

Rule ND1905 Immutability

Related to Fields should be declared as private: matches public or internal, mutable fields assigned from outside their parent class and subclasses. Fields are implementation details and should be private.

When a non-private field misbehaves, the culprit can be anywhere; a private field can only be assigned from its own class, usually one source file to look at.

How to fix

Declare matched fields protected or better private. A field exclusively referencing immutable states can stay accessible but must be declared readonly.

Estimated Debt: 5 minutes per method outside the parent hierarchy assigning the field.

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>A field must not be assigned from outside its parent hierarchy types</Name>
// <Id>ND1905:AFieldMustNotBeAssignedFromOutsideItsParentHierarchyTypes</Id>

warnif count > 0
from f in JustMyCode.Fields.Where(f => 
      (f.IsInternal || f.IsPublic) && 
      !f.IsGeneratedByCompiler && 
      !f.IsImmutable && 
      !f.IsEnumValue)

let methodsAssignerOutsideOfMyType = f.MethodsAssigningMe.Where(
     m =>!m.IsGeneratedByCompiler &&
          m.ParentType != f.ParentType && 
         !m.ParentType.DeriveFrom(f.ParentType) )

where methodsAssignerOutsideOfMyType.Any()

select new { 
   f, 
   methodsAssignerOutsideOfMyType,
   Debt = (5*methodsAssignerOutsideOfMyType.Count()).ToMinutes().ToDebt(),
   Severity = Severity.High
}

//<Expl>
// The *{0}* is assigned outside its parent type by the *{1}*.
// A field should be an encapsulated *implementation detail*.
// Consider making it *private* or refactor it as a property 
// whose accesses can be better controlled at debug-time.
//</Expl>

//<Desc>
// Related to *Fields should be declared as private*: matches **public or
// internal, mutable fields** assigned from outside their parent class and
// subclasses. Fields are **implementation details** and should be private.
//
// When a *non-private field* misbehaves, the culprit can be anywhere; a
// private field can only be assigned from its own class, usually one source
// file to look at.
//</Desc>

//<HowToFix>
// Declare matched fields *protected* or better *private*. A field
// exclusively referencing immutable states can stay accessible but must be
// declared readonly.
//
// Estimated Debt: 5 minutes per method outside the parent hierarchy
// assigning the field.
//</HowToFix>

Immutability: all 15 items