In Kathleen Dollard's recent blog post, she presents an interesting reason to use nested classes in .net. However, she also mentions that FxCop doesn't like nested classes. I'm assuming that the people writing FxCop rules aren't stupid, so there must be reasoning behind that position, but I haven't been able to find it.
相关问题
- Generic Generics in Managed C++
- What uses more memory in c++? An 2 ints or 2 funct
- How to Debug/Register a Permanent WMI Event Which
- 'System.Threading.ThreadAbortException' in
- Bulk update SQL Server C#
From Sun's Java Tutorial:
Why Use Nested Classes? There are several compelling reasons for using nested classes, among them:
Logical grouping of classes—If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.
Increased encapsulation—Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.<- This doesn't apply to C#'s implementation of nested classes, this only applies to Java.More readable, maintainable code—Nesting small classes within top-level classes places the code closer to where it is used.
I often use nested classes to hide implementation detail. An example from Eric Lippert's answer here:
This pattern becomes even better with use of generics. See this question for two cool examples. So I end up writing
instead of
Also I can have a generic list of
Equality<Person>
but notEqualityComparer<Person, int>
where as
is not possible. That's the benefit of nested class inheriting from parent class.
Another case (of the same nature - hiding implementation) is when you want to make a class's members (fields, properties etc) accessible only for a single class:
It depends on the usage. I rarely would ever use a Public nested class but use Private nested classes all of the time. A private nested class can be used for a sub-object that is intended to be used only inside the parent. An example of this would be if a HashTable class contains a private Entry object to store data internally only.
If the class is meant to be used by the caller (externally), I generally like making it a separate standalone class.
Bear in mind that you'll need to test the nested class. If it is private, you won't be able to test it in isolation.
You could make it internal, though, in conjunction with the
InternalsVisibleTo
attribute. However, this would be the same as making a private field internal only for testing purposes, which I consider bad self-documentation.So, you may want to only implement private nested classes involving low complexity.
In addition to the other reasons listed above, there is one more reason that I can think of not only to use nested classes, but in fact public nested classes. For those who work with multiple generic classes that share the same generic type parameters, the ability to declare a generic namespace would be extremely useful. Unfortunately, .Net (or at least C#) does not support the idea of generic namespaces. So in order to accomplish the same goal, we can use generic classes to fulfill the same goal. Take the following example classes related to a logical entity:
We can simplify the signatures of these classes by using a generic namespace (implemented via nested classes):
Then, through the use of partial classes as suggested by Erik van Brakel in an earlier comment, you can separate the classes into separate nested files. I recommend using a Visual Studio extension like NestIn to support nesting the partial class files. This allows the "namespace" class files to also be used to organize the nested class files in a folder like way.
For example:
Entity.cs
Entity.BaseDataObject.cs
Entity.BaseDataObjectList.cs
Entity.IBaseBusiness.cs
Entity.IBaseDataAccess.cs
The files in the visual studio solution explorer would then be organized as such:
And you would implement the generic namespace like the following:
User.cs
User.DataObject.cs
User.DataObjectList.cs
User.IBusiness.cs
User.IDataAccess.cs
And the files would be organized in the solution explorer as follows:
The above is a simple example of using an outer class as a generic namespace. I've built "generic namespaces" containing 9 or more type parameters in the past. Having to keep those type parameters synchronized across the nine types that all needed to know the type parameters was tedious, especially when adding a new parameter. The use of generic namespaces makes that code far more manageable and readable.
The nested classes can be used for following needs: