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:11

It looks okay when your classes are small. Once they get bloated, you really start thinking about moving them in separate files.

More to your point, if you want to use both A.B and M.B in the same code you have to always type A.B and M.B, which can be a pain.

查看更多
【Aperson】
3楼-- · 2020-04-03 06:13

There's nothing inherently wrong about nested classes, as long as you stick to the following rules of thumb:

  1. Never public or internal. There are special cases, such as when you're using a nested class to implement IEnumerator. But even then, the class itself should be kept private, since instances of it are being returned as IEnumerator, and it's really just being done as a way to avoid junking up the namespace with classes that aren't supposed to be instantiated.

  2. Keep them small. A private nested class that's really just used for storing and passing around data in a more organized way is fine, and can sometimes be a very useful tool. (Not entirely unlike how anonymous classes are useful.) But if you're looking to use them to package up large chunks of functionality, it becomes a code smell that suggests you might want to consider refactoring the outer class instead.

查看更多
Lonely孤独者°
4楼-- · 2020-04-03 06:16

Well you can use namespaces to do things like this too (just create a new folder in VS). Which is better for organising and will pretty much give you the same result.

But if the subclass is only relevant to the parent class then I don't see the harm in it.

Then again, if you are calling them the same thing I would guess they do a similar drop and you may want to look into abstraction, perhaps your parent classes could be done differently too. Really depends on what you need them to do though

查看更多
萌系小妹纸
5楼-- · 2020-04-03 06:17

If class B has any similarities between each inner class instance, would it make sense for you to abstract the similarities of B to a base class that exists alongside A, M, and Q? (I think so.) Then your inner classes, while they may have the same name, would be a little cleaner.

With that said, this type of structure can be seen for things like Metadata in an MVC application. In that instance you'd have something like:

[MetadataType(typeof(A.Metadata))]
class A
{
    protected class Metadata
    {
        ...
    }
}

[MetadataType(typeof(B.Metadata))]
class B
{
    protected class Metadata
    {
        ...
    }
}

In these case the inner classes each serve the same purpose but their implementations vary with each parent class. Also, with the Metadata definitions here, it makes a lot of sense to keep a class that helps describe its parent as an inner class. If there's any chance you might want to re-use the inner classes elsewhere then I would move them outside of their parents.

I think it's a little atypical to see this in practice otherwise. I'm sure there are good examples, but I bet there are more bad examples of this type of pattern.

查看更多
等我变得足够好
6楼-- · 2020-04-03 06:25

I understand your sample is sort of contrived. Still, if your class names are similar enough - or identical - you really shouldn't make them nested classes. As a general rule you should shy away from using nested classes at all.

If I'm remembering correctly, the .NET Framework Guidelines recommends against using nested classes as well. Nested Type Usage Guidelines is a little old (back to version 1.1), but the principles still apply.

Do not use nested types if the following are true:

  • The type must be instantiated by client code. If a type has a public constructor, it probably should not be nested. The rationale behind this guideline is that if a nested type can be instantiated, it indicates that the type has a place in the library on its own. You can create it, use it, and destroy it without using the outer type. Therefore, it should not be nested. An inner type should not be widely reused outside of the outer type without a relationship to the outer type.
  • References to the type are commonly declared in client code.
查看更多
Rolldiameter
7楼-- · 2020-04-03 06:25

I like doing that, for me it makes the use more clearer and especially finding names less of a problem. But usally i try to limit this on private classes or public enums. For example

class Text {
   enum Alignment

class UIElement {
   enum Alignment

or

class Quadtree {
   private class Node

class Octree {
   private class Node
查看更多
登录 后发表回答