Fake
Fake

Reputation: 131

c# alternative for enum to get intellisense advantages

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?

Upvotes: 4

Views: 657

Answers (2)

Imantas
Imantas

Reputation: 1662

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.

Upvotes: 3

Visual Vincent
Visual Vincent

Reputation: 18320

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;

Upvotes: 5

Related Questions