Nested types should not be visible
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.
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>
Open in the interactive Rules Explorer · All default rules
Design: all 16 items
- Avoid custom delegates ND1300
- Types with disposable instance fields must be disposable ND1301
- Disposable types with unmanaged resources should declare finalizer ND1302
- Methods that create disposable object(s) and that don't call Dispose() ND1303
- Disposable Types Must Unsubscribe Events ND1315
- Classes that are candidate to be turned into structures ND1304
- Avoid namespaces with few types ND1305
- Nested types should not be visible ND1306
- Declare types in namespaces ND1307
- Empty static constructor can be discarded ND1308
- Instances size shouldn't be too big ND1309
- Attribute classes should be sealed ND1310
- Don't use obsolete types, methods or fields ND1311
- Do implement methods that throw NotImplementedException ND1312
- Override equals and operator equals on value types ND1313
- Boxing/unboxing should be avoided ND1314