Fields that could have a lower visibility

Rule ND1802 Visibility

Warns about fields declarable with a lower visibility (private < internal < public) without compilation error. Narrowing visibility promotes encapsulation by minimizing consumption scope.

Publicly visible fields are not matched (the rule cannot know if public was intentional); matched public fields are declared in non-public types.

Fields tagged CannotDecreaseVisibilityAttribute or IsNotDeadCodeAttribute (from NDepend.API.dll, or declared in your own code) are not matched.

How to fix

Declare each matched field with the optimal visibility shown in the CouldBeDeclared column.

If you publish an API, some matched public fields should stay public: either add && !m.IsPubliclyVisible to the rule (coarse), or tag each field with CannotDecreaseVisibilityAttribute (finer).

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 that could have a lower visibility</Name>
// <Id>ND1802:FieldsThatCouldHaveALowerVisibility</Id>

warnif count > 0 from f in JustMyCode.Fields where 
  f.Visibility != f.OptimalVisibility &&

  // Eliminate public fields visible outside of their assembly
  // because the rule cannot know if the developer left the field public 
  // intentionally or not.
 !f.IsPubliclyVisible &&
 
  // Don't match potentially dead fields, candidate for removal
  f.MethodsUsingMe.Any() &&

 !f.HasAttribute("NDepend.Attributes.CannotDecreaseVisibilityAttribute".AllowNoMatch()) &&
 !f.HasAttribute("NDepend.Attributes.IsNotDeadCodeAttribute".AllowNoMatch()) &&
 !f.HasAttribute("JetBrains.Annotations.UsedImplicitlyAttribute".AllowNoMatch()) &&
  // If you don't want to link NDepend.API.dll, you can use your own attributes
  // and adapt the source code of this rule.
  
  // JSON and XML serialized fields must remain public.
 !f.ParentType.TypesUsed.Any(t1 => t1.IsAttributeClass && 
   (t1.ParentNamespace.Name == "Newtonsoft.Json" || t1.ParentNamespace.Name == "System.Text.Json")
  ) &&
 !f.HasAttribute("System.Xml.Serialization.XmlElementAttribute".AllowNoMatch()) && 
 !f.HasAttribute("System.Xml.Serialization.XmlAttributeAttribute".AllowNoMatch()) &&
 !f.HasAttribute("System.Xml.Serialization.XmlArrayAttribute".AllowNoMatch()) &&
 !f.HasAttribute("System.Xml.Serialization.XmlArrayItemAttribute".AllowNoMatch()) &&
 
  // Don't check for serialized fields visibility
 !f.HasAttribute("System.Runtime.Serialization.DataMemberAttribute".AllowNoMatch()) &&
 
  // Fields of classes that derive from Unity classes might be used implicitly by the Unity engine
 !f.ParentType.BaseClasses.Any(bc => bc.ParentNamespace.Name.StartsWithAny("UnityEngine","UnityEditor"))

select new { 
   f, 
   f.Visibility , 
   CouldBeDeclared = f.OptimalVisibility,
   f.MethodsUsingMe,

   Debt = 30.ToSeconds().ToDebt(), // It is fast to change the field visibility
   Severity = Severity.Medium
}

//<Expl>
// In the context of analyzed code, the *{0}* can be declared as *{2}*.
// Doing so **improves encapsulation** by constraining this field's accessibility 
// to the smallest possible scope.
//</Expl>

//<Desc>
// Warns about fields declarable with a lower visibility (*private* <
// *internal* < *public*) without compilation error. **Narrowing visibility**
// **promotes encapsulation** by minimizing consumption scope.
//
// Publicly visible fields are not matched (the rule cannot know if public
// was intentional); matched public fields are declared in non-public types.
//
// Fields tagged *CannotDecreaseVisibilityAttribute* or
// *IsNotDeadCodeAttribute* (from *NDepend.API.dll*, or declared in your own
// code) are not matched.
//</Desc>

//<HowToFix>
// Declare each matched field with the *optimal visibility* shown in the
// *CouldBeDeclared* column.
//
// If you publish an API, some matched public fields should stay public:
// either add *&& !m.IsPubliclyVisible* to the rule (coarse), or tag each
// field with *CannotDecreaseVisibilityAttribute* (finer).
//</HowToFix>

Visibility: all 12 items