Why Would I Ever Need to Use C# Nested Classes

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 nested Classes in C# and C++ - Why and When?

Hmm this might call for a very suggestive answer and therefore many will disagree with my answer. I am one of those people who believe that there is no real need for nested classes and I am tended to agree with your statement:

My 'gut instinct' in this regard is that doing so is simply due to extremely poor methodology

Cases where people feel the need to design nested classes is where functionality that is tightly coupled to the behavior designed in the outer class. E.g. event handling can be designed in an inner class, or the Threading behavior can find its way to inner classes.

I rather refactor specific behavior out of the 'outer' class so that I end up with two smaller classes that both have clear responsibilities.

To me the main drawback of designing inner classes is that they tend to clutter functionality which is hard(er) to use with principals as TDD (test driven development).

If you are not relying on test driven principals, I think it will not harm you a lot. It is (like so many things) a matter of taste, not a matter of right or wrong. I learned that the topic can lead to long and exhausting discussion. Quite similar to whether you should use static helper classes that tend to do more than just 'be a helper' and are getting more and more state over time.

The discussions can become a lot more concrete if you ever run into a real life example. Until then it will be mostly people's "gut feeling".

C#, is it okay to use nested classes for logical structure?

The .net Design Guide advises against it:

  • "Do not use public nested types as a logical grouping construct; use namespaces for this."
  • "Avoid publicly exposed nested types. The only exception to this is when variables of the nested type need to be declared in rare scenarios such as subclassing or other advanced customization scenarios."

That's also what the base class library does: In the System.Web.UI namespace, you have DataGridItem, DataListItem, ListViewItem, MenuItem, RepeaterItem, etc. All of these could be called Item and nested inside DataGrid, DataList, etc. However, this would violate the two principles outlined above.

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 we use inner classes?

Some inner classes are exposed publicly (eg Map.Entry in Java) but that is by far the exception rather than the norm.

Inner classes are, basically, an implementation detail.

For example, Swing makes extensive use of inner classes for event listeners. Without them you would end up polluting the global namespace with a bunch of classes you otherwise don't need to see (which may make their purpose harder to determine).

Essentially inner classes are a form of scope. Package access hides classes from outside the package. Private inner classes hide that class from outside that class.

Inner classes in Java are also a substitute for a lack of function pointers or method delegates (which are in C#) or closures. They are the means of passing a function to another function. For example, in the Executor class you have:

void execute(Runnable r);

so you can pass a method in. In C/C++ that could be achieved with:

void execute(void (*run)());

being a pointer to a function.

c# Public Nested Classes or Better Option?

The contents of a class should be the implementation details of that class. Are the nested classes implementation details of the outer class, or are you merely using the outer class as a convenient name scoping and discovery mechanism?

If the former, then you shouldn't be making the private implementation details publically available. Make them private if they are implementation details of the class.

If the latter, then you should be using namespaces, not outer classes, as your scoping and discovery mechanism.

Either way, public nested classes are a bad code smell. I'd want to have a very good reason to expose a nested class.



Related Topics



Leave a reply



Submit