From time to time, people new to .NET ask about the utility of nested classes -- especially since FxCop recommends against using them in publicly visible APIs. It took me a while, but I've compiled a list of 101 uses for nested classes -- public or otherwise.
001: Separating instance-identity from type-scope
FxCop lists "nested enumerators" as an exception to its ExternallyVisibleNestedTypesShouldNotBeUsed rule. The idea here is that enumerator objects often need access to private/protected members of the collection, but they need to be instantiated separately from their parent collections, so that clients can perform 2 or more enumerations of the same collection, concurrently.
The use of a nested class solves both of these problems -- a nested class is just like any other type in that it can be instantiated on its own, but it's special in that it has full access to the private/protected members of its outer (or "parent") class.
A similar example is found in asynchronous I/O callback implementations (although these rarely, if ever, should be part of a publicly visible API design). The nature of Stream.BeginRead all but mandates that a separate object be instantiated to handle the callback, in order to maintain a reference to the buffer (to get at the data) alongside a reference to the underlying Stream object (to call End/BeginRead). And yet, the callback routine might legitimately need access to the private members of its class, so again, a nested class is useful in this case.
010: Encapsulating details from yourself
Despite the best of intentions, sometimes a class can grow so large as to become unmanageable. You know what I'm talking about -- you most often see these classes in files named "Form1.vb". <kidding>
But seriously, once a class grows to over a couple hundred lines long, you can no longer visually inspect the code in just one or two presses of the PgDn key -- and coding becomes more error-prone.
Recently, I was developing a Form-derived class with a lot of expensive (but seldom needed) member fields. In order to conserve memory and improve startup time, I wanted to delay initializing these member variables until they were needed -- a classic "delay load" activation scheme. But the form code was growing into a petty large beast, and I found it difficult to remember to always check the delay-load fields for 'null' before using them.
At the expense of a little extra typing, I discovered that nested classes provide a nice way to encapsulate the delay-load initialization policy, so it becomes impossible to mishandle those members -- encapsulating the instantiation means never having to check for 'null':
private class LazyResource { SomeBigResource _heavyObject = null; public SomeBigResource LazyLoad { get { if (_heavyObject == null) _heavyObject = new SomeBigResource(); return _heavyObject; } } } private LazyResource heavyObject;
011: Enforcing error-checking for p/invoke declarations
Most folks I know consider it a best practice to consolidate all Win32 interop declarations into an internal class, typically named 'Win32'. I agree, but I like to take it one step further, and enforce proper error-checking.
However, it's not always practical to mark the p/invoke method declarations as private, and wrap them with error-safe methods of the same name -- the two methods would be ambiguously named. Obviously, one could simply prefix "Safe" on the error-safe wrapper methods (or vice versa: prefix the raw methods with "Unsafe"), but it's just as easy to be explicit, and shield the raw p/invoke declarations in a private, nested class.
There is some creative license, here -- you can name the inner class(es) after the
Win32 DLL that exports the functions ("Kernel32", "User32", etc) or you can sort the
functions based on security considerations (applying [SuppressUnmanagedCodeSecurity]
to some, but not all, and to assist in code-review as FxCop
recommends). Or you can lump them all into one big nested class, if you're lazy
and in a hurry. The
point is, nested classes afford an extra measure of flexibility in this case, while also
providing the opportunity to enforce proper handling of return codes, and proper
marshaling of arguments.
100: Simulating VB's "parameterful properties" feature, in C#
This one comes from Mike Woodring and Keith Brown... I don't really recommend this technique, but it's an interesting curiosity nonetheless. I'm fascinated by VB's parameterized properties -- one of the few true language features it offers that C# does not.
http://www.bearcanyon.com/dotnet/#PropertyArgSim
101: Pretending that namespaces have the ability to bear attributes, methods and fields
Namespaces don't really exist, in the CLR. Types exist, and they have names -- these names can include the '.' character, and by convention we refer to the portion before the final '.', if any, as the namespace.
We use namespaces to organize our types into logical functional groupings, but because
they don't really exist, we can't apply attributes to them. In some instances, it
might make sense to use nested classes where you might otherwise use a namespace, if you
wish to apply a certain attribute to everything inside. I've already mentioned
[SuppressUnmanagedCodeSecurity], but there are probably a few other examples...
[ComVisible]? [StrongNameIdentityPermission] (and other CodeAccessSecurity attributes)?
I'd heed FxCop's advice, here, and never use a nested class in place of a namespace in any public-facing API design, just to save cutting and pasting a few attribute tags -- that's clearly Not Right. I include it here only to round out the list to 101 interesting uses for nested classes. Hope you've enjoyed them -- happy nesting!
