In Praise of Nested Classes

I love nested classes. You can do elegant thing wit them that otherwise require a ton of code – even if its generated. But the rest of the world seems confused by the syntax. Assuming a class named Budget, we could have Budget.List refer to a class (not an instance).

 

Public Class Budget
  ‘ Other Stuff

   Public Class List
      ‘ Stuff
   End Class

End Class

 

Unfortunately, the rest of the world is either confused by them, hasn’t been introduced, or is following the Microsoft party line that they are uncool as expressed via FxCop. So to a large extent this post is a requiem. I have decided not to do what I’m describing here in my current architecture. At least today.

Since I think it is such a huge loss, I want to show you what nested classes can accomplish. Imagine an architecture tat contains these classes (with other meaningful stuff deleted):

 

Public MustInherit Class BizEntityBase(Of TEntity As EntityBase(Of TEntity))
End Class

Public Class Budget
   Inherits BizEntityBase(Of Budget)

End Class

Public Class BudgetList
   Inherits BizListBase(Of Budget)

   Protected Sub New(ByVal list As IEnumerable(Of Budget))
      MyBase.New(list)
   End Sub

   Public Function GetItem(ByVal id As Guid) As Budget
      Dim q = From entity In Me Where entity.BudgetGuid = id
      Return q.SingleOrDefault
   End Function

   Public Shared Function GetList() As BudgetList
      Return GetListInternal(Of BudgetList)()
   End Function

End Class

In this scenario, you have a copy for BudgetList for every single entity – probably hundreds adding many thousands of lines of code. Sure you can generate it, but it’s better to reuse code than generate it. Now, use a nested class:

Public MustInherit Class BizEntityBase(Of TEntity As BizEntityBase(Of TEntity))

Public Class List
   Inherits BizListBase(Of TEntity)

   Protected Sub New(ByVal list As IEnumerable(Of TEntity))
      MyBase.New(list)
   End Sub

   Public Function GetItem(ByVal id As Guid) As TEntity
      Dim q = From entity In Me Where entity.PrimaryKeyValue = id
      Return q.SingleOrDefault
   End Function

   Public Shared Function GetList() As EntityBase(Of TEntity).List
      Return GetListInternal(Of EntityBase(Of TEntity).List)()
   End Function
End Class

End Class

Public Class Budget
   Inherits BizEntityBase(Of Budget)

End Class

As a result of this change, there is ONE location for the List functionality reused by all classes. There is no BudgetList class to be generated or handcrafted.It’s not needed.

But external code must use Budget.List to access the class. I asked a smart structural architect know about this. He didn’t even grok the question until I explained it. So for now, I’m skipping this approach at the same time I’m throwing it out there for other people to gnaw on.

Although I’m not completely skipping it. The entity list classes I’m writing derive and leverage base class code so are less lines than I’m showing above. But it’s still hundreds of extra classes I see as existing only because as an industry we’ve yet to wrap our heads around this concept.

5 thoughts on “In Praise of Nested Classes”

  1. I didn’t know about the FxCop rule. I was aware of the existence of nested classes for a while but I only truly understood their value when I studied the System.Collections.Generic namespace in detail.

  2. Lorenzo,

    I could go look, but off the top of my head I can’t think of a place nested classes areused in Collections.Generic. That’s a newer namespace, after nested classes were listed as “uncool” by FxCop so perhaps it indicates that I’m taking too strong a view against them. Could you point out one or two places Generic uses nested classes?

    Kathleen

  3. Kathleen

    I was thinking about the generic collections that expose their (nested) enumerator type. Although I am not sure why this was done exactly this way. I mean the enumerator is implemented as a nested type anyway and type information is thus propagated automatically. Access to the enumerator is provided by means of the (generic) IEnumerable interface just like with the nongeneric collections. Could this be a design decision? Maybe I am missing something.

    By researching this whole thing I learned about the potential of nesting types in a generic type. I started to think of scenarios where you could take advantage of propagation of type information. I came up with the following. Imagine a generic class that has a (public) event. The event provides the consumer of the class with some data so we would need a custom EventArgs class. However, the type of the data field/property is dependent on the type of the class. Wouldn’t it be nice to provide the consumer of the class with a typesafe field? All we have to do to achieve this, is nest the custom EventArgs class in the generic class.

    Have a nice day
    Lorenzo

  4. Lorenzo,

    Thanks for following up on this. I’ve been a bit distracted the last few days.

    The key difference between the iterators and what I want to do is that outside code is not aware the class is nested. It only interacts through the interface.

    Kathleen

  5. At first look, it looks brilliant , I thought I could have saved a lot of classes. But then I realize that why we have to build a nested class for the list if we do have already generic classes in .net like List .
    As per my concern If i have to write any custom collection class then I am also interesting to write some custom functionality for each class , but I didn’t see any custom activity which I can do for each class which already made by the Nested List Class. Can you elaborate me the concept behind generating this list class.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>