C#, is it okay to use nested classes for logical s

2020-04-03 05:26发布

I am having a bit of a debate about the use of nested classes. The situation is that a class name makes sense to be repeated in two or more places, and while there is moderate similarity between each of the different instances, they are generally different. The nested classes are not often (if at all) needed beyond the scope of their parent class.

So then, rather than just coming up with three different class names, this seems to make more sense to me.

class A {
   class B {
}

class M {
   class B {
   }
}

class Q {
   class B {
   }
}

The obvious problem with that is not functionality, but rather consistency/repetition. I was wondering if other developers have ever struggled with the same thing, and what some of the opinions were.

11条回答
孤傲高冷的网名
2楼-- · 2020-04-03 06:29

The .net Design Guide advises against it:

  • "Do not use public nested types as a logical grouping construct; use namespaces for this."
  • "Avoid publicly exposed nested types. The only exception to this is when variables of the nested type need to be declared in rare scenarios such as subclassing or other advanced customization scenarios."

That's also what the base class library does: In the System.Web.UI namespace, you have DataGridItem, DataListItem, ListViewItem, MenuItem, RepeaterItem, etc. All of these could be called Item and nested inside DataGrid, DataList, etc. However, this would violate the two principles outlined above.

查看更多
你好瞎i
3楼-- · 2020-04-03 06:29

I would say it is sometimes ok, but usually not a good design, to use private nested classes. I once refactored an existing very large class in my project to give it private nested classes. The reason why I did this was that some methods took dozens of parameters and this gave them a more logical grouping. In this sense I see nested classes as a good quick fix. It made sense because no one outside that class had any use for any of those fields.

Generally, I would shy away from using nested classes in an initial design - and think twice before considering them in a redesign. In maintenance, if you have the time, it is better to redesign the whole class and split them out into separate classes in separate files that are internal.

I think this strategy is also better for testability than using nested classes is. Due to greater dependencies with the outer class and other classes in the application, my refactored nested classes weren't much easier to unit test than the original large class that passed around many parameters. If you split nested classes so that they are on their own, you can write more discrete unit tests that actually test units rather than, effectively, combining the unit tests for the outer class and the inner class. This will give you more confidence in saying, "Yes, the inner class works at the unit test level" and "Yes, the outer class works at the unit test level" (which also tests how it fits together with the inner class, e.g. in computing formulas).

查看更多
够拽才男人
4楼-- · 2020-04-03 06:30

It really depends on the functionality of the nested class. That is very similar to the way the C++ STL defined iterator differently in each class. There's nothing wrong with the practice, per se, as long as the concept of each is truly different based on the encompassing class.

It can be, somewhat, a matter of style and taste, but personally I don't see an issue as long as they are truly different and dependent on the definition of the encapsulating class. It does tend to get more confusing, though, if they are publicly visible outside the class. Thus, I would not personally expose the classes publicly.

查看更多
beautiful°
5楼-- · 2020-04-03 06:33

Don't create a nested class if there is any chance (or business reason) that you'll have to use it in some other place (use namespace instead and dot not hesitate to create class with long name if you need to).

For instance I use nested class for DTO between my controller and my view, or in a class to represent a cache entry.

查看更多
家丑人穷心不美
6楼-- · 2020-04-03 06:33

If you want to name them the same but have different types you could use different namespaces.

Namespace1.MyClass{}
Namespace2.MyClass{}

This will end up with two different types despite the classes being named the same.

查看更多
登录 后发表回答