Fields should be declared as private or protected
Matches mutable (non-constant, non-readonly) fields non-private, non-protected. Fields are implementation details and should be private (or protected if derived classes need them).
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.
Debt is proportional to the number of methods assigning the field.
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.
Debt is proportional to the number of methods assigning the field.
How to fix
Declare the field private or readonly, refactoring outside usage away if possible. If external access is required, encapsulate it in a property: debug breakpoints on accessors simplify tracking read-write accesses.
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>Fields should be declared as private or protected</Name>
// <Id>ND1805:FieldsShouldBeDeclaredAsPrivate</Id>
warnif count > 0
let isUnityProject = ThirdParty.Assemblies.Any(a => a.Name.StartsWith("UnityEngine"))
from f in JustMyCode.Fields where
// In Unity projects often there is no properties for high-performance reasons
// and public fields are used instead.
!isUnityProject &&
// Valid encapsulation level
!f.IsPrivate && !f.IsProtected && !f.IsProtectedAndInternal &&
// These conditions filter cases where fields
// doesn't represent state that should be encapsulated.
!f.IsGeneratedByCompiler &&
!f.IsSpecialName &&
!f.IsInitOnly &&
!f.IsLiteral &&
!f.IsEnumValue &&
!f.HasAttribute("System.Xml.Serialization.XmlAttributeAttribute".AllowNoMatch()) &&
!f.HasAttribute("System.Runtime.Serialization.DataMemberAttribute".AllowNoMatch()) &&
!f.HasAttribute("System.Runtime.CompilerServices.FixedBufferAttribute".AllowNoMatch())
// A non-private field used from outside its class,
// usually leads to complicated field state management.
let outsideMethodsUsingMe =
f.MethodsUsingMe.Where(m => m.ParentType != f.ParentType)
// Don't report fields assigned from outside its parent type
// since this situation is handled by the rule
// 'A field must not be assigned from outside its parent hierarchy types'
where !f.MethodsAssigningMe.Intersect(outsideMethodsUsingMe).Any()
select new {
f,
f.Visibility,
outsideMethodsUsingMe,
Debt = (60+20*outsideMethodsUsingMe .Count()).ToSeconds().ToDebt(),
// The cost to leave such issue unfixed is higher if the field is publicly visible!
AnnualInterest = Severity.Medium.AnnualInterestThreshold() * (f.IsPubliclyVisible ? 3 : 1)
}
//<Expl>
// The *{0}* is used outside its parent type by the *{2}*.
// A field should be an encapsulated *implementation detail*.
// Consider making it *private* or refactor it as a property
// whose read-write accesses can be better controlled at debug-time.
//</Expl>
//<Desc>
// Matches **mutable (non-constant, non-readonly) fields non-private,
// non-protected**. Fields are **implementation details** and should be
// private (or protected if derived classes need them).
//
// 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.
//
// Debt is proportional to the number of methods assigning the field.
//</Desc>
//<HowToFix>
// Declare the field *private* or *readonly*, refactoring outside usage away
// if possible. If external access is required, encapsulate it in a property:
// debug breakpoints on accessors simplify tracking read-write accesses.
//</HowToFix>
Open in the interactive Rules Explorer · All default rules
Visibility: all 12 items
- Methods that could have a lower visibility ND1800
- Types that could have a lower visibility ND1801
- Fields that could have a lower visibility ND1802
- Types that could be declared as private, nested in a parent type ND1803
- Avoid publicly visible constant fields ND1804
- Fields should be declared as private or protected ND1805
- Constructors of abstract classes should be declared as protected or private ND1806
- Avoid public methods not publicly visible ND1807
- Event handler methods should be declared as private or protected ND1808
- Wrong usage of CannotDecreaseVisibilityAttribute ND1809
- Exception classes should be declared as public ND1810
- Methods that should be declared as 'public' in C#, 'Public' in VB.NET