249

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.

yas4891
  • 4,774
  • 3
  • 34
  • 55
  • I wonder how many other questions have this exact same subject line? Come on, Dan! What _about_ C# Nested Classes? – John Saunders Jul 04 '09 at 21:51
  • 2
    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 :-{ – H H Jul 04 '09 at 23:03
  • 7
    You're right. There's a lot about them, but not "why". Closest I found was http://stackoverflow.com/questions/454218/private-inner-classes-in-c-why-arent-they-used-more-often, 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. – John Saunders Jul 04 '09 at 23:15
  • 4
    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. – hardyVeles Dec 19 '17 at 22:45

8 Answers8

297

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.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • @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 – Mohit Shah Feb 07 '16 at 17:01
  • 1
    @EricLippert Ok a nested member can access members accessible to containing type, got it – Mohit Shah Feb 07 '16 at 17:08
  • 7
    Right. Private means accessible in the type. Nested members are by definition in the type. – Eric Lippert Feb 07 '16 at 17:14
131

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.

Noldorin
  • 144,213
  • 56
  • 264
  • 302
  • 52
    In fact, the .NET Framework Guidelines explicitly recommend against creating public nested classes. – Mark Seemann Jul 04 '09 at 22:43
  • @Mark: I wasn't aware of that, but it definitely makes sense. They are usually only appropiate as private/protected or in the rare case internal (when acesss from without the class isn't common). – Noldorin Jul 04 '09 at 22:51
  • 5
    @Henk: I think Mark is referring to this page: http://msdn.microsoft.com/en-us/library/tdz1bea9(VS.71).aspx – Noldorin Jul 04 '09 at 23:49
  • The public-inside-public class can be useful, for example on factories: new MyObject.Factory() on which the create() would return a MyObject instance. Not really sure if this applies to C#, but I suppose it's a general design pattern. – Jorn Jul 04 '09 at 23:54
  • @Jon: The factory pattern applies perfectly well to C#. However, the factory class is usually defined directly within the namespace (i.e. not nested), which makes sense in this case. – Noldorin Jul 05 '09 at 00:17
  • 6
    One more example that MS doesn't adhere to its own recommendation: Just see `System.Windows.Forms.ListView` nested classes! – Mehrdad Afshari Jul 05 '09 at 02:24
  • @Noldorin, @Mark: that page merely advices against public constructors on nested classes. – H H Jul 05 '09 at 08:31
  • 1
    @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). – Noldorin Jul 05 '09 at 10:01
  • @Mehrdad: Indeed, that is the case. I have found it to be a slight nuisance when wanting to use ListViewItem objects in code. – Noldorin Jul 05 '09 at 10:05
  • @Noldorin: Same for me. Fortunately `var` has fixed the issue nowadays... too late, now we have WPF! – Mehrdad Afshari Jul 05 '09 at 23:11
  • @Mehrdad: Yeah, exactly. `var` is (almost) always your friend. WinForms apps haven't yet disappeared though, so it still helps. :) – Noldorin Jul 05 '09 at 23:18
  • 4
    Better MSDN article on this - http://msdn.microsoft.com/en-us/library/ms229027.aspx – akjoshi Dec 21 '11 at 12:08
  • If a public nested class has a private constructor; then it is totally valid to have a public nested class. Some rules are rules and some rules are opinions. – Dave Lawrence Jun 20 '13 at 14:04
  • @dravel: Yeah, that's a fair enough exception to the rule of thumb. – Noldorin Jun 20 '13 at 14:12
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);
    }
}
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • Additionally, I find the internal working of how a foreach works absolutely amazing. Thanks! – Karthik Feb 28 '12 at 07:07
  • 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, IEnumerable, IEnumerator, and IEnumerator. The parent class is assumed to be a List object with stored numbers. And "foreach" would call GetEnumerator when looping through the list. Too much complexity missed.... – Stokely Sep 08 '21 at 06:41
51

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.

ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • the advantage is only item 1, if you exclude it, you can use `protected`, thus "using `private` fields" becomes thing-in-itself – jungle_mole Dec 13 '15 at 20:17
  • 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. – ChrisW Mar 06 '17 at 17:10
39

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);
        }
    }
}
codersl
  • 2,222
  • 4
  • 30
  • 33
Arjan Einbu
  • 13,543
  • 2
  • 56
  • 59
  • Except, the `FirstNameComparer` class should be static, as well as the `Compare` method. – ErikE Nov 20 '15 at 01:51
  • @erike: not if your implementing the IComparer interface, as I did... – Arjan Einbu Nov 20 '15 at 17:09
  • I suppose that you are right! – ErikE Nov 20 '15 at 17:12
  • 1
    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 – ni3.net May 29 '16 at 07:01
20

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.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 1
    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 Jul 04 '09 at 23:06
  • @jerryjvl That is actually quite significant! +1 for sure as it keeps code even more secure. – julealgon Jan 07 '14 at 14:34
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.

Fernando
  • 4,029
  • 1
  • 26
  • 35
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)

lambertwm
  • 56
  • 1
  • 4
    Unfortunately when doing this, the convention of `public Settings Settings { get; set; }` goes out the window. – Dan Lugg May 31 '13 at 18:02