Private Inner Classes in C# - Why Aren't They Used More Often

Private inner classes in C# - why aren't they used more often?

Nested classes (probably best to avoid the word "inner" as nested classes in C# are somewhat different to inner classes in Java) can indeed be very useful.

One pattern which hasn't been mentioned is the "better enum" pattern - which can be even more flexible than the one in Java:

public abstract class MyCleverEnum
{
public static readonly MyCleverEnum First = new FirstCleverEnum();
public static readonly MyCleverEnum Second = new SecondCleverEnum();

// Can only be called by this type *and nested types*
private MyCleverEnum()
{
}

public abstract void SomeMethod();
public abstract void AnotherMethod();

private class FirstCleverEnum : MyCleverEnum
{
public override void SomeMethod()
{
// First-specific behaviour here
}

public override void AnotherMethod()
{
// First-specific behaviour here
}
}

private class SecondCleverEnum : MyCleverEnum
{
public override void SomeMethod()
{
// Second-specific behaviour here
}

public override void AnotherMethod()
{
// Second-specific behaviour here
}
}
}

We could do with some language support to do some of this automatically - and there are lots of options I haven't shown here, like not actually using a nested class for all of the values, or using the same nested class for multiple values, but giving them different constructor parameters. But basically, the fact that the nested class can call the private constructor gives a lot of power.

Why/when should you use nested classes in .net? Or shouldn't you?

Use a nested class when the class you are nesting is only useful to the enclosing class. For instance, nested classes allow you to write something like (simplified):

public class SortedMap {
private class TreeNode {
TreeNode left;
TreeNode right;
}
}

You can make a complete definition of your class in one place, you don't have to jump through any PIMPL hoops to define how your class works, and the outside world doesn't need to see anything of your implementation.

If the TreeNode class was external, you would either have to make all the fields public or make a bunch of get/set methods to use it. The outside world would have another class polluting their intellisense.

What are reasons why one would want to use nested classes?

You've answered your own question. Use nested classes when you need a helper class that is meaningless outside the class; particularly when the nested class can make use of private implementation details of the outer class.

Your argument that nested classes are useless is also an argument that private methods are useless: a private method might be useful outside of the class, and therefore you'd have to make it internal. An internal method might be useful outside of the assembly, and therefore you'd make it public. Therefore all methods should be public. If you think that's a bad argument, then what is different about you making the same argument for classes instead of methods?

I make nested classes all the time because I am frequently in the position of needed to encapsulate functionality in a helper that makes no sense outside of the class, and can use private implementation details of the outer class. For example, I write compilers. I recently wrote a class SemanticAnalyzer that does semantic analysis of parse trees. One of its nested classes is LocalScopeBuilder. Under what circumstances would I need to build a local scope when I am not analyzing the semantics of a parse tree? Never. That class is entirely an implementation detail of the semantic analyzer. I plan to add more nested classes with names like NullableArithmeticAnalyzer and OverloadResolutionAnalyzer that are also not useful outside of the class, but I want to encapsulate rules of the language in those specific classes.

People also use nested classes to build things like iterators, or comparators - things that make no sense outside of the class and are exposed via a well-known interface.

A pattern I use quite frequently is to have private nested classes that extend their outer class:

abstract public class BankAccount
{
private BankAccount() { }
// Now no one else can extend BankAccount because a derived class
// must be able to call a constructor, but all the constructors are
// private!
private sealed class ChequingAccount : BankAccount { ... }
public static BankAccount MakeChequingAccount() { return new ChequingAccount(); }
private sealed class SavingsAccount : BankAccount { ... }

and so on. Nested classes work very well with the factory pattern. Here BankAccount is a factory for various types of bank account, all of which can use the private implementation details of BankAccount. But no third party can make their own type EvilBankAccount that extends BankAccount.

Using Inner classes in C#

Typically I reserve inner-classes for one of two purposes:

  1. Public classes which derive from their parent class where the parent class is an abstract base implementation with one or more abstract methods and each subclass is an implementation which serves a specific implementation. after reading Framework Design and Guidelines I see that this is marked as "Avoid", however I use it in scenarios similar to enums--althogh that's probably giving a bad impression as well

  2. The inner classes are private and are units of business logic or otherwise tightly coupled to their parent class in a manner in which they are fundamentally broken when consumed or used by any other class.

For all other cases I try to keep them in the same namespace and the same accessibility level as their consumer/logical parent--often with names that are a little less friendly than the "main" class.

On big projects you'd be surprised how often you may find yourself initially building a strongly-coupled component just because it's first or primary purpose makes it seem logical--however unless you have a very good or technical reason to lock it down and hide it from sight then there is little harm in exposing the class so that other components can consume it.

Edit Keep in mind that even though we're talking about sub-classes they should be more-or-less well designed and loosely coupled components. Even if they are private and invisible to the outside world keeping a minimal "surface area" between classes will greatly ease the maintainability of your code for future expansion or alteration.

When does encapsulation trump SOLID - public vs private c# class?

Usually, nested types (either class or struct, including enumerations) are used for some kind of contextual data and/or behavior, which doesn't have any sense without its context.

E.g., you could make nested types for some interop API, when you don't want to provide access to that API from external code, or you're using some kind of helper data container, which provides functionality, useful only for surrounding class.

So, even making these types internal can bring confusion to other developers (especially, where a single project is being edited by several people).

I don't see, how SOLID is broken here - nesting the type is just a limiting of type scope. It is not an extending of functionality of the surrounding class.

Why Aren't Operator Overloads Used More Frequently?

They are not used very frequently because often it doesn't make sense to have mathematical operations (which the majority of operators are) over most classes of objects. The semantics of the operations you want are usually different in some way. You wouldn't use addition against a bunch of OrderLine objects, for example, when you actually want aggregation or grouping.

To use the example that you have now provided in the comments for your question, "+" may seem like a decent way to put child elements into a parent element but the operations have entirely different semantics. "+" suggests that you would be adding them together mathematically, when in fact you are aiming for a hierarchial relationship between the two. It may make sense to you, but I imagine that on first read it is probably not obvious to a lot of programmers.

They're rarely used because they rarely fit.

Java (anonymous or not) inner classes: is it good to use them?

In my view, 90% of inner classes in Java code are either entities that are associated with a single class and were thus "shoved in" as inner classes, or anonymous inner classes that exist because Java does not support Lambdas.

I personally don't like seeing complex inner classes. They add complexity to the source file, they make it bigger, they're ugly to deal with in terms of debugging and profiling, etc. I like separating my project into many packages, in which case I can make most entities top-level classes that are restricted to the package.

That leaves me with necessary inner classes - such as action listeners, fake "functional" programming, etc. These are often anonymous and while I'm not a fan (would have preferred a Lambda in many cases), I live with them but don't like them.

I haven't done any C# in years, but I'm wondering if the prevalence of inner classes or whatever the C# equivalent is dropped when they introduced Lambdas.



Related Topics



Leave a reply



Submit