Nested types should not be visible

Rule ND1306 Design

Warns about nested types not declared private. Nested types serve to encapsulate private implementation details of the containing type and should not be externally visible. Do not use them for logical grouping or name collision avoidance — use namespaces. Protected nested types can be used in subclasses.

How to fix

Change the type's accessibility if it needn't be externally visible; otherwise make it non-nested. For grouping, use a namespace instead.

Estimated Debt: 2 minutes per nested type plus 4 minutes per outer type using it.

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>Nested types should not be visible</Name>
// <Id>ND1306:NestedTypesShouldNotBeVisible</Id>

warnif count > 0 from t in JustMyCode.Types where 
  t.IsNested && 
 !t.IsGeneratedByCompiler &&
 !t.IsPrivate &&

 // It is accepted that non-private nested types are declared inside Razor page classes.
 !t.OutterTypes.Any(ot => ot.DeriveFrom("Microsoft.AspNetCore.Mvc.RazorPages.PageModel".AllowNoMatch()) ||
                          ot.DeriveFrom("Microsoft.AspNetCore.Components.ComponentBase".AllowNoMatch()))
                          
let typesUser = t.TypesUsingMe.Where(t1 => t1 != t.ParentType && t1.ParentType != t.ParentType)
select new { 
   t, 
   t.Visibility,
   typesUser,
   Debt = (2 + 4*typesUser.Count()).ToMinutes().ToDebt(),
   Severity = Severity.Medium
} 

//<Expl>
// The *nested {0}* is declared as *{1}* and is accessed outside 
// its parent type by the *{2}*. Typically, types are nested to 
// encapsulate private implementation details.
// Consider making it *private* or non-nested.
//</Expl>

//<Desc>
// Warns about nested types not declared private. Nested types serve to
// encapsulate private implementation details of the containing type and
// should not be externally visible. Do not use them for logical grouping or
// name collision avoidance — use namespaces. Protected nested types can be
// used in subclasses.
//</Desc>

//<HowToFix>
// Change the type's accessibility if it needn't be externally visible;
// otherwise make it *non-nested*. For grouping, use a namespace instead.
//
// Estimated Debt: 2 minutes per nested type plus 4 minutes per outer type
// using it.
//</HowToFix>

Design: all 16 items