Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# alternative for enum to get intellisense advantages

Tags:

c#

I have a base class

abstract public class ComponentBase
{
    public List<string> Actions { get; set; }

    protected abstract void RegisterActions();
}

and its child

public class VideoBase : ComponentBase
{
    protected override void RegisterActions()
    {
        base.Actions.Add("Start video");
        base.Actions.Add("Pause video");
        base.Actions.Add("Rewind video");
    }
}

But to make things easier i also create enum type

public enum Actions
{
    START_VIDEO,
    PAUSE_VIDEO,
    REWIND_VIDEO,
}

What i want is to force every child of ComponentBase to have its own enum Actions but it seems its not easy to do. Alternatively i though about changing Actions List to Dictionary<string, string>but it doesn't give me intellisense advantage. I want for user of this class to easily get "list" of actions in intellisense, instead of checking what string value they have to put, any suggestions?

like image 679
Fake Avatar asked Jan 26 '23 22:01

Fake


2 Answers

How about using generics in your base class?

abstract public class ComponentBase<T> where T : struct
{
    //Example property.
    public T Action { get; set; }
}

As InBetween mentioned, in C# 7.3 you can add an additional constraint to force the generic type to be an enum:

abstract public class ComponentBase<T> where T : struct, System.Enum

That way you get to specify which enum to use when inheriting ComponentBase in your child class:

public class VideoBase : ComponentBase<VideoActions>
{
    ...your code...
}

public enum VideoActions
{
    START_VIDEO,
    PAUSE_VIDEO,
    REWIND_VIDEO
}
VideoBase video = new VideoBase();

//video.Action will now be of type VideoActions.
video.Action = VideoActions.START_VIDEO;
like image 157
Visual Vincent Avatar answered Jan 30 '23 09:01

Visual Vincent


In case you want to have this enum-like implementation to restrict the value to a specific subset of string values, there is a solution for this. You could create a class with private constructor and static fields:

public class Action
{
    /// <summary>
    /// Start video
    /// </summary>
    public static readonly Action START_VIDEO = new Action("Start video");

    /// <summary>
    /// Pause video
    /// </summary>
    public static readonly Action PAUSE_VIDEO = new Action("Pause video");

    /// <summary>
    /// Rewind video
    /// </summary>
    public static readonly Action REWIND_VIDEO = new Action("Rewind video");


    private readonly string _value;

    private Action(string value)
    {
        _value = value;
    }

    public override string ToString()
    {
        return _value;
    }

    public static implicit operator string(Action action)
    {
        return action._value;
    }
}

And whenever you restrict any input to Action, like your list for example

public List<Action> Actions { get; set; }

or something like

public void RegisterAction(Action action) { }

Which will restrict the value to one of those declared in the Action class rather than allowing any string to be used.

You can then do the Actions.Add(<intellisense suggestions show up>) enter image description here

and still use it as string within your code if needed:

// Implicit conversion
string someValue = Action.START_VIDEO;

// .ToString() override
Console.WriteLine("Action: " + Action.START_VIDEO);

In both cases the code will use the string representation declared in the class instead of the name as it would be in enum case.

Furthermore, by providing the description in <summary> you also get the advantage of seeing the actual value when hovering mouse over reference to Action.

like image 37
Imantas Avatar answered Jan 30 '23 07:01

Imantas