Reputation: 131
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
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>)
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
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