22

What's wrong with using nested classes to group constants?

Like so:

public static class Constants
{
    public static class CategoryA
    {
        public const string ValueX = "CatA_X";
        public const string ValueY = "CatA_Y";
    }
    public static class CategoryB
    {
        public const string ValueX = "CatB_X";
        public const string ValueY = "CatB_Y";
    }
}

Used like so:

Console.WriteLine(Constants.CategoryA.ValueY);
Console.WriteLine(Constants.CategoryB.ValueX);

You could also make the "Constants"-class partial...

Michael Damatov
  • 15,253
  • 10
  • 46
  • 71

3 Answers3

23

There is some guideline (updated for fx 4.5) against public nested classes:

√ DO use nested types when the relationship between the nested type and its outer type is such that member-accessibility semantics are desirable.

X AVOID publicly exposed nested types. The only exception to this is if variables of the nested type need to be declared only in rare scenarios such as subclassing or other advanced customization scenarios.

X DO NOT use nested types if the type is likely to be referenced outside of the containing type.

I think your example matches the first point (ie: you're good).

Community
  • 1
  • 1
H H
  • 263,252
  • 30
  • 330
  • 514
  • Great to hear, any thoughts on why this use isn't more widespread - I can't be the only one who thought of it? –  May 31 '10 at 20:45
  • Maybe you overestimate the use-cases. Constants are usually organized quite naturally alongside their classes. And classes shouldn't grow so big that their members need grouping. – H H May 31 '10 at 21:02
  • 1
    Too many constants are definitely a potential sign of a bad design; however in my case we're talking about SharePoint which uses constants heavily. –  Jun 01 '10 at 09:36
  • This scenario is perfect for unit testing and producing test data. I wouldn't advise it as a go to for normal class design however. – Michael Brown Mar 08 '15 at 04:42
  • 1
    It looks like the linked documentation has been updated to include this point: "DO NOT use public nested types as a logical grouping construct; use namespaces for this." This seems to contradict the answer now. – Leon7C Jan 05 '18 at 14:47
  • `The only exception to this is if variables of the nested type need to be declared only in rare scenarios such as subclassing or other advanced customization scenarios` ? sample? – Kiquenet May 08 '20 at 09:57
3

Who said it was wrong? Constants can be (and are) defined anywhere in a class hierarchy.

egrunin
  • 24,650
  • 8
  • 50
  • 93
  • Yes, I think it's pretty neat - but I haven't seen it done so I'm suspecting that there are some side effects... –  May 31 '10 at 19:24
  • 2
    I think it's not about the constants but the nested classes. – H H May 31 '10 at 19:49
  • 1
    Actually using Nested Classes For constants allows you to completely override or to extend them for sub-classes. There's added benefit to the concept. – Aren May 31 '10 at 21:25
2

Not saying that what you did is wrong, but what about using namespaces instead like this:

namespace Constants
{
    public static class CategoryA
    {
        public const string ValueX = "CatA_X";
        public const string ValueY = "CatA_Y";
    }
    public static class CategoryB
    {
        public const string ValueX = "CatB_X";
        public const string ValueY = "CatB_Y";
    }
}
juharr
  • 31,741
  • 4
  • 58
  • 93
  • Yup, that would work when you have two levels - Category and Value but with nested classes you can add an infinite number of levels; ie Languages.English.American = "en-US". –  May 31 '10 at 20:43
  • (Without adding additional namespaces I should add...) –  May 31 '10 at 20:47
  • 1
    But why not add namespaces? In some situations that might be better, you can add to a ns in another file/assembly. – H H May 31 '10 at 20:59
  • 4
    Yes, but the downside of using namespaces is that you can't have constants "on" them. Also with classes you could add properties that get default values/combine constants etc programmatically. –  Jun 01 '10 at 09:34