I don’t agree. I don’t agree that they’re any more harmful than any other C# construct (except goto…). Nested types are like anything else in our tool-belt: they have a time and place and can be abused.
But, when to use them? Well, for the most part I agree with Michael, you should avoid them. But, there are times when they’re simply the best solution in a given set of circumstances.
Let’s look at asynchronous programming model (APM) in .NET.
// Paraphrased from MSDN
// Accept one client connection asynchronously.
public static void DoBeginAcceptTcpClient(TcpListener
// Start to listen for connections from a client.
Trace.WriteLine("Waiting for a connection...");
// Accept the connection.
// BeginAcceptSocket() creates the accepted socket.
// Process the client connection.
public static void DoAcceptTcpClientCallback(IAsyncResult ar)
// Get the listener that handles the client request.
TcpListener listener = (TcpListener)ar.AsyncState;
// End the operation and display the received data on
// the console.
TcpClient client = listener.EndAcceptTcpClient(ar);
// TODO: do something with client.
// Process the connection here. (Add the client to a
// server table, read data, etc.)
Trace.WriteLine("Client connected completed");
In this simple scenario we are getting by with a state of simply a TcpListener object. In a more complex scenario, you’ll likely also want a connection-specific queue, some sort of information about what to do after a connection, etc. While you can use existing types of have several collection instance fields to keep track of each of these things; you then have to introduce synchronization of those collections, managing the content of those collections, etc.–it’s much easier and safer to send that information on the stack. One method I’ve tried is simply passing an Object collection as the state; but that quickly becomes hard to manage because of the lack of type-safety on the elements in the array (if I remove an element and replace it with another type, the compile can’t know and I’ll get a run-time error instead of a compile-time error). To get type safety I generally introduce a new type to aggregate all the types I need in this asynchronous callback. While this new type *could* be reusable by other classes; it likely isn’t and I don’t want to then be bound that that explicit contract I’ve signed by making the types publicly available. The only option of not making them publicly available is as private nested types. For example:
I find this use of nested types to be more object-oriented (the needs of the DoAcceptTcpClientCallback are abstracted), more intention revealing, better implements Single Responsibility Principle (SRP), better separates concerns, more maintainable and more agile.
Now, to be clear; this is forced set of circumstances. You’re using a library that implements the APM (right? You haven’t implemented APM yourself…). But, that’s my point–nested types are almost essential in a given set of circumstances.