0

In C#, is it possible to return a reference to a static class?

I hope the following LinqPad example (which doesn't compile) explains what I'm thinking of:

void Main()
{
    var x = GetConstants(); 
    x.C1.Dump();
}

public Type GetConstants() =>
    (DateTime.Now.DayOfWeek == DayOfWeek.Saturday 
     || DateTime.Now.DayOfWeek == DayOfWeek.Sunday) 
        ? AllConstants.WeekendConstants
        : AllConstants.WeekdayConstants;
}

public static class AllConstants
{
    public static class WeekdayConstants
    {
        public const string C1 = "Weekday_C1";
        public const string C2 = "Weekday_C2";
    }

    public static class WeekendConstants
    {
        public const string C1 = "Weekend_C1";
        public const string C2 = "Weekend_C2";
    }
}
DrGriff
  • 4,394
  • 9
  • 43
  • 92
  • 8
    There's no such thing as an *instance* of a static class; that's the entire point of static classes. – Daniel Mann Jun 13 '19 at 17:13
  • It seems like `WeekdayConstants` and `WeekendConstants` should be `string[]` or some collection of `string`s, not `class`es in the first place. Then instead of fields with numeric suffixes you'd just index into the collection. – Lance U. Matthews Jun 13 '19 at 17:21
  • 1
    It looks like what you want is to return a thing with a `C1` and `C2` property. In that case, you could declare an interface with those properties and have two implementations. The method returns that interface. Or you could declare some `enum` in place of `C1` and return `Func`. – Scott Hannen Jun 13 '19 at 17:29
  • @ScottHannen Not a bad idea but I feel like this might be overkill. Maybe op just really simplified the question, in that case this would make sense. – Joelius Jun 13 '19 at 17:34
  • 2
    This sure sounds like an XY problem -- that is, you have some real problem, you have some bad solution in mind, and now you're asking questions about the bad solution rather than the real problem. What's the real problem? – Eric Lippert Jun 13 '19 at 17:39

2 Answers2

1

For using the Type Type (which seems to be the right thing in this scenario) you will have to wrap the classname in a typeof. Doing so will result in typeof(AllConstants.WeekendConstants) and return the type of said class at compile time.

Keep in mind that this will not let you access the constants directly like you tried to in your Main method. To get those, you will have to look at this question.
My use of typeof will however give you the Type object you need for then getting all the constants of said class.

The compiling code would look like this:
As already mentionend, you will not be able to call the constants directly because this will only return a Type representing the static class.

public Type GetConstants() =>
    (DateTime.Now.DayOfWeek == DayOfWeek.Saturday
        || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
        ? typeof(AllConstants.WeekendConstants)
        : typeof(AllConstants.WeekdayConstants);

Also on a sidenote. As already mentionend in the comments by BACON, using static classes with constans for this might not be the best solution. From the looks of it I think a dictionary would be best suited. Think something like this:

public static class WeekConstants
{
    public static Dictionary<string, string> Weekdays { get; } = new Dictionary<string, string>()
    {
        { "C1", "Weekday_C1" },
        { "C2", "Weekday_C2" },
    };

    public static Dictionary<string, string> Weekends { get; } = new Dictionary<string, string>()
    {
        { "C1", "Weekend_C1" },
        { "C2", "Weekend_C2" },
    };
}

In this code I use a readonly property (more here). This is obviously not a constant but the closest you'll get by using a dictionary.
It might also be a good idea to use an Enum instead of a string as key so you could ask for a weekday using DayEnum.C1 instead of "C1".

Joelius
  • 3,839
  • 1
  • 16
  • 36
0

If the goal is to ensure that the values used are stored in constants, you can achieve that without having to pass around the types containing those constants. If your method returns a Type you would have to use reflection to try to find the constants you want in those types. You can't get them to behave like interfaces or non-static class instances.

You could do define a type which represents a set of those values and then populate it using your constants:

public class ThingWithValues // because I don't know what these things are
{
    public ThingWithValues(string c1, string c2)
    {
        C1 = c1;
        C2 = c2;
    }

    public string C1 { get; }
    public string C2 { get; }
}

public ThingWithValues GetValues() =>
    (DateTime.Now.DayOfWeek == DayOfWeek.Saturday
     || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
        ? new ThingWithValues(AllConstants.WeekendConstants.C1, AllConstants.WeekendConstants.C2)
        : new ThingWithValues(AllConstants.WeekdayConstants.C1, AllConstants.WeekdayConstants.C2);

Because there are only two variations of these - weekend and weekday, you could even define them as static members like this:

public class ThingWithValues
{
    public ThingWithValues(string c1, string c2)
    {
        C1 = c1;
        C2 = c2;
    }

    public string C1 { get; }
    public string C2 { get; }

    public static ThingWithValues Weekend { get; } =
        new ThingWithValues(AllConstants.WeekendConstants.C1, AllConstants.WeekendConstants.C2);

    public static ThingWithValues Weekday { get; } =
        new ThingWithValues(AllConstants.WeekdayConstants.C1, AllConstants.WeekdayConstants.C2);
}

And then the usage becomes

public ThingWithValues GetValues() =>
    (DateTime.Now.DayOfWeek == DayOfWeek.Saturday
     || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
        ? ThingWithValues.Weekend
        : ThingWithValues.Weekday;

Or add the "is weekend" check into another static member within ThingWithValues:

public static ThingWithValues ForDate(DateTime date) =>
    date.DayOfWeek == DayOfWeek.Saturday
     || date.DayOfWeek == DayOfWeek.Sunday
        ? Weekend
        : Weekday;

Now the usage becomes

var x = ThingWithValues.ForDate(DateTime.Now);
Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
  • If you give `ThingWithValues` a private constructor, you end up with something I had to google to see if it was a thing - a doubleton. It's like a singleton, where you can only have one instance, but now there are two possible instances. I'm not saying that's a good thing or that we should look for opportunities to use doubletons, even though they're twice as good as singletons. – Scott Hannen Jun 13 '19 at 17:58