The most common is to use the internal type as private and so it works as an auxiliary type that can only be accessed internally. It’s a form of composition with a type that only concerns the type in question. That is, if the internal type will not be used elsewhere has no reason to expose it to other parts of the code.
You can thus hide an implementation detail by leaving more organized the part that is the detail. In most cases it is a matter of organization.
An important detail is that the internal type can access external type members, even private ones, without problems if necessary. Everything that has been created in a more external scope continues in the same scope. Nesting works in the same way as found in method algorithms.
I wouldn’t know how to quote an example where it would be appropriate to create a nested kind that is public.
Researching found some interesting examples in the OS, especially in Eric Lippert’s response where it shows a way where you can create your own hierarchy but prevent others from doing so:
public abstract class BankAccount {
private BankAccount() {} // prevent third-party subclassing.
private sealed class SavingsAccount : BankAccount { ... }
private sealed class ChequingAccount : BankAccount { ... }
public static BankAccount MakeSavingAccount() { ... }
public static BankAccount MakeChequingAccount() { ... }
}
I put in the Github for future reference.
Note that he uses private
and does not leave the default. In C# classes, by default sane internal
, or are visible throughout Assembly. It would be almost the same as leaving public
, after all you are creating a class within another but it would be accessible outside of it, so it would not have much advantage.
I don’t know how it is with C#, but if I remember well in Java there was another utility for nested types, even public - ensuring a compositional relationship between the "outside" type and the "inside" type. Because if to build an internal instance you always need an external reference (eg.:
a = new A(); b = a.new B()
) it is ensured that the composition exists and theA
is never null (although the namespace ofB
is polluted by the internal limbs ofA
...). I don’t know if this makes sense in C# - or even if it’s a good idea in Java - but here’s the example.– mgibsonbr