Reputation: 1885
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?
Upvotes: 5
Views: 20055
Reputation: 70307
Depending on your use case, you may wish to use a master/subset pattern.
For example, I have one enum that contains every possible value:
/// <summary>
/// Types of limits that can be applied to a table, view, or table-value function query.
/// </summary>
/// <remarks>Databases are expected to provide their own enumeration that represents a subset of these options.</remarks>
[Flags]
public enum LimitOptions
{
/// <summary>
/// No limits were applied.
/// </summary>
None = 0,
/// <summary>
/// Returns the indicated number of rows with optional offset
/// </summary>
Rows = 1,
/// <summary>
/// Returns the indicated percentage of rows. May be applied to TableSample
/// </summary>
Percentage = 2,
/// <summary>
/// Adds WithTies behavior to Rows or Percentage
/// </summary>
WithTies = 4,
/// <summary>
/// Returns the top N rows. When there is a tie for the Nth record, this will cause it to be returned.
/// </summary>
RowsWithTies = Rows | WithTies,
/// <summary>
/// Returns the top N rpercentage of ows. When there is a tie for the Nth record, this will cause it to be returned.
/// </summary>
PercentageWithTies = Percentage | WithTies,
Then each project has its own subset of values:
/// <summary>
/// Limit options supported by Access.
/// </summary>
/// <remarks>This is a strict subset of LimitOptions</remarks>
public enum AccessLimitOption
{
/// <summary>
/// No limits were applied.
/// </summary>
None = LimitOptions.None,
/// <summary>
/// Uses TOP
/// </summary>
RowsWithTies = LimitOptions.RowsWithTies,
}
Rather than making the enumeration extensible, the subprojects always use a strict subset. This allows me to keep the core fairly generic, while offering database specific APIs where appropriate.
Upvotes: 1
Reputation: 3476
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
}
Upvotes: 6
Reputation: 43886
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.
Upvotes: 9