252

I'm trying to understand about nested classes in C#. I understand that a nested class is a class that is defined within another class, what I don't get is why I would ever need to do this.

4
  • I wonder how many other questions have this exact same subject line? Come on, Dan! What about C# Nested Classes? Commented Jul 4, 2009 at 21:51
  • 4
    John, i agree that it was asked before, but both a search on "C# Nested Classes" and the Related panel on the right contain no direct duplicates. Blame it on SO search :-{ Commented Jul 4, 2009 at 23:03
  • 7
    You're right. There's a lot about them, but not "why". Closest I found was stackoverflow.com/questions/454218/…, and you'd have to know that inner and nested meant the same thing. Maybe it's not search, but maybe this is actually the first at this level. Commented Jul 4, 2009 at 23:15
  • 7
    While I really get the point with "duplicate question" flagging, still can-t resist the internal emotional drive to share my impression that people around here are super trigger happy about shooting the "duplicate" flag. While these probably understand the programming languages way better then me - it's somehow appears that they have issues with proper interpretation of English, especially when a noob asks something. I'm happy to see you two guys caring enough to understand the difference in knowledge-levels at which one is facing his issue - good to have you here. Commented Dec 19, 2017 at 22:45

8 Answers 8

303

A pattern that I particularly like is to combine nested classes with the factory pattern:

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() { ... } } 

By nesting the classes like this, I make it impossible for third parties to create their own subclasses. I have complete control over all the code that runs in any bankaccount object. And all my subclasses can share implementation details via the base class.

Sign up to request clarification or add additional context in comments.

3 Comments

@EricLippert how would the constructor of base class be called in this case since it is private? And if the base class constructor cannot be called how can a derived class instance be created? Sorry if this is not related to the post but I am just trying to understand the code and its use
@EricLippert Ok a nested member can access members accessible to containing type, got it
Right. Private means accessible in the type. Nested members are by definition in the type.
135

The purpose is typically just to restrict the scope of the nested class. Nested classes compared to normal classes have the additional possibility of the private modifier (as well as protected of course).

Basically, if you only need to use this class from within the "parent" class (in terms of scope), then it is usually appropiate to define it as a nested class. If this class might need to be used from without the assembly/library, then it is usually more convenient to the user to define it as a separate (sibling) class, whether or not there is any conceptual relationship between the two classes. Even though it is technically possible to create a public class nested within a public parent class, this is in my opinion rarely an appropiate thing to implement.

14 Comments

In fact, the .NET Framework Guidelines explicitly recommend against creating public nested classes.
@Henk: I think Mark is referring to this page: msdn.microsoft.com/en-us/library/tdz1bea9(VS.71).aspx
One more example that MS doesn't adhere to its own recommendation: Just see System.Windows.Forms.ListView nested classes!
@Henk: Actually, the second line states "Public nested types should be used rarely". The "both" conditions it then refers to, I am not sure about, however (there is only one bullet point).
|
56

what I don't get is why I would ever need to do this

I think you never need to do this. Given a nested class like this ...

class A { //B is used to help implement A class B { ...etc... } ...etc... } 

... you can always move the inner/nested class to global scope, like this ...

class A { ...etc... } //B is used to help implement A class B { ...etc... } 

However, when B is only used to help implement A, then making B an inner/nested class has two advantages:

  • It doesn't pollute the global scope (e.g. client code which can see A doesn't know that the B class even exists)
  • The methods of B implicitly have access to private members of A; whereas if B weren't nested inside A, B wouldn't be able to access members of A unless those members were internal or public; but then making those members internal or public would expose them to other classes too (not just B); so instead, keep those methods of A private and let B access them by declaring B as a nested class. If you know C++, this is like saying that in C# all nested classes are automatically a 'friend' of the class in which they're contained (and, that declaring a class as nested is the only way to declare friendship in C#, since C# doesn't have a friend keyword).

When I say that B can access private members of A, that's assuming that B has a reference to A; which it often does, since nested classes are often declared like this ...

class A { //used to help implement A class B { A m_a; internal B(A a) { m_a = a; } ...methods of B can access private members of the m_a instance... } ...etc... } 

... and constructed from a method of A using code like this ...

//create an instance of B, whose implementation can access members of self B b = new B(this); 

You can see an example in Mehrdad's reply.

2 Comments

the advantage is only item 1, if you exclude it, you can use protected, thus "using private fields" becomes thing-in-itself
The nested class isn't necessarily a subclass (which can use protected). For example, the outer class might be some kind of container, and the nested class might be an iterator for that container: the iterator wants access to the member data / implementation details of the container.
54

A nested class can have private, protected and protected internal access modifiers along with public and internal.

For example, you are implementing the GetEnumerator() method that returns an IEnumerator<T> object. The consumers wouldn't care about the actual type of the object. All they know about it is that it implements that interface. The class you want to return doesn't have any direct use. You can declare that class as a private nested class and return an instance of it (this is actually how the C# compiler implements iterators):

class MyUselessList : IEnumerable<int> { // ... private List<int> internalList; private class UselessListEnumerator : IEnumerator<int> { private MyUselessList obj; public UselessListEnumerator(MyUselessList o) { obj = o; } private int currentIndex = -1; public int Current { get { return obj.internalList[currentIndex]; } } public bool MoveNext() { return ++currentIndex < obj.internalList.Count; } } public IEnumerator<int> GetEnumerator() { return new UselessListEnumerator(this); } } 

2 Comments

Additionally, I find the internal working of how a foreach works absolutely amazing. Thanks!
I really appreciate this example. I think for many new C# people there are lots of hidden assumption and processes going on not described. For example, there's four hidden interfaces working in tandem here: IEnumerable<T>, IEnumerable, IEnumerator<T>, and IEnumerator. The parent class is assumed to be a List<int> object with stored numbers. And "foreach" would call GetEnumerator when looping through the list. Too much complexity missed....
40

There is good uses of public nested members too...

Nested classes have access to the private members of the outer class. So a scenario where this is the right way would be when creating a Comparer (ie. implementing the IComparer interface).

In this example, the FirstNameComparer has access to the private _firstName member, which it wouldn't if the class was a separate class...

public class Person { private string _firstName; private string _lastName; private DateTime _birthday; //... public class FirstNameComparer : IComparer<Person> { public int Compare(Person x, Person y) { return x._firstName.CompareTo(y._firstName); } } } 

4 Comments

Except, the FirstNameComparer class should be static, as well as the Compare method.
@erike: not if your implementing the IComparer<T> interface, as I did...
I suppose that you are right!
you can use this scenario with private nested and create static method to expose the instance of IComparer in the Top level class. cause in this case nested class is not useful for other classes so make instance privatly rather than give control to other's
21

There are times when it's useful to implement an interface that will be returned from within the class, but the implementation of that interface should be completely hidden from the outside world.

As an example - prior to the addition of yield to C#, one way to implement enumerators was to put the implementation of the enumerator as a private class within a collection. This would provide easy access to the members of the collection, but the outside world would not need/see the details of how this is implemented.

2 Comments

Which has the added benefit that code using such an implemented interface cannot sneakily cast the interface back to the implementing class, because it is nested and private so it cannot be referenced.
@jerryjvl That is actually quite significant! +1 for sure as it keeps code even more secure.
6

Nested classes are very useful for implementing internal details that should not be exposed. If you use Reflector to check classes like Dictionary<Tkey,TValue> or Hashtable you'll find some examples.

Comments

4

Maybe this is a good example of when to use nested classes?

// ORIGINAL class ImageCacheSettings { } class ImageCacheEntry { } class ImageCache { ImageCacheSettings mSettings; List<ImageCacheEntry> mEntries; } 

And:

// REFACTORED class ImageCache { Settings mSettings; List<Entry> mEntries; class Settings {} class Entry {} } 

PS: I've not taken into account which access modifiers should be applied (private, protected, public, internal)

1 Comment

Unfortunately when doing this, the convention of public Settings Settings { get; set; } goes out the window.