Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to enum in design pattern

Consider the case of a base assembly base having an enum type like

public enum ItemState = { red, green, blue };

I use this base assembly within other assemblies Project_1, Project_2 and so on.

Each of them does some specific stuff, and requires project-specific states, like {grey, black, white, ...} in Project_1 and {brown, transparent, ...} in Project_2.

Project_1 isn't allowed to use (and if possible even see) {brown, transparent, ...}. Similarly, Project_2 cannot use {grey, black, white, ...}.

I know "partial enum" doesn't exist - so what is the suggested design pattern for such a task?

like image 450
neggenbe Avatar asked Dec 11 '22 15:12

neggenbe


2 Answers

Since enums cannot be inherited from, one solution might be to use a class with static constant members like this:

public class ItemState
{
    protected ItemState() { }

    public static ItemState red { get; } = new ItemState();
    public static ItemState green { get; } = new ItemState();
    public static ItemState blue { get; } = new ItemState();
}

Then in your Project_1 you can derive an own class:

public class ItemState_1 : ItemState
{
    public static ItemState grey { get; } = new ItemState_1();
    public static ItemState black white { get; } = new ItemState_1();
}

And in Project_2

public class ItemState_2 : ItemState
{
    public static ItemState brown { get; } = new ItemState_2();
    public static ItemState transparent white { get; } = new ItemState_2();
}

It's probably not the most comfortable way, but the best I can think of right now.

And you can use them like that:

ItemState project1State = ItemState_1.grey;

if (project1State == ItemState_1.grey)
   // do something

This all compiles fine, but unfortunatly those value cannot be used in a switch/case statement. This could be worked around with proper ToString() implementation, string literals can be used in switch/case. But that would of course add more code to those class/property definitions.

like image 137
René Vogt Avatar answered Dec 19 '22 14:12

René Vogt


I am a bit late, but here is "buffed" version of Rene`s answer (now with implicit casting!):

public class ColorEnum
{
    protected readonly string Name;
    protected readonly Color Value;

    public static readonly ColorEnum Red = new ColorEnum(Color.Red, "Red");
    public static readonly ColorEnum Green = new ColorEnum(Color.Green, "Green");
    public static readonly ColorEnum Blue = new ColorEnum(Color.Blue, "Blue");

    protected ColorEnum(Color value, string name)
    {
        Name = name;
        Value = value;
    }

    public override string ToString()
    {
        return Name;
    }

    public static implicit operator Color(ColorEnum @enum)
    {
        return @enum.Value;
    }

    public static implicit operator string(ColorEnum @enum)
    {
        return @enum.Name;
    }
}

public class AnotherColorEnum : ColorEnum
{
    public static readonly ColorEnum Grey = new AnotherColorEnum(Color.Gray, "Grey");
    public static readonly ColorEnum Black = new AnotherColorEnum(Color.Black, "Black");
    public static readonly ColorEnum White = new AnotherColorEnum(Color.White, "White");

    protected AnotherColorEnum(Color value, string name) : base(value, name)
    {
    }
}

This way you may use your "enum" like this:

    var color = ColorEnum.Red;
    var anothercolor = Color.Red;
    if (color == anothercolor)
    {
            //DoSomething
    }

Or like this:

    var color = ColorEnum.Red;
    var anothercolor = "Red";
    if (color == anothercolor)
    {
            //DoSomething
    }
like image 43
Szer Avatar answered Dec 19 '22 14:12

Szer