正如 Andriy 所提到的,在这种情况下,使用 OneOf 或 Either 等可区分联合可能很有用。
如果您只是将枚举用作 ID,您还可以创建各种类并利用类型系统进行模式匹配。如果您喜欢针对特定项目进行模式匹配,这只是一种不同的模式。
internal abstract class EnumType
{
protected EnumType(int value, string name)
{
if(value < 0) { throw new InvalidOperationException("Value cannot be less than 0."); }
this._value = value;
this._name = name ?? throw new ArgumentNullException(nameof(name));
}
public static implicit operator int(EnumType x)
=> x?._value ?? throw new ArgumentNullException(nameof(x));
public static implicit operator string(EnumType x)
=> x?._name ?? throw new ArgumentNullException(nameof(x));
private readonly int _value;
private readonly string _name;
}
internal sealed class eUnit : EnumType
{
private eUnit(int value, string name): base(value, name) { }
// operator overloads like |, &, ^, etc...
internal static readonly eUnit Villager = new eUnit(0, "Villager");
internal static readonly eUnit Warrior = new eUnit(1, "Warrior");
internal static readonly eUnit Wizard = new eUnit(2, "Wizard");
}
internal sealed class eItem : EnumType
{
private eItem(int value, string name): base(0, "Apple") { }
// operator overloads like |, &, ^, etc...
internal static readonly eItem Apple = new eItem(0, "Apple");
internal static readonly eItem Steak = new eItem(1, "Steak");
internal static readonly eItem Pizza = new eItem(2, "Pizza");
}
这将允许您编写:
var myList = new List<EnumType>();
myList.Add(eUnit.Warrior);
myList.Add(eItem.Pizza);
if (myList[0] is eUnit eUnit)
{
DoStuff();
}
如果您关心进一步的粒度,您也可以将这些静态字段转换为类,如下所示:
internal abstract class eUnit : EnumType
{
private eUnit(int value, string name): base(value, name) { }
// operator overloads like |, &, ^, etc...
internal sealed class Villager : eUnit
{
private Villager(): base(0, "Villager") { }
internal static readonly Villager _ = new Villager();
}
internal sealed class Warrior : eUnit
{
private Warrior(): base(1, "Warrior") { }
internal static readonly Warrior _ = new Warrior();
}
internal sealed class Wizard : eUnit
{
private Wizard(): base(2, "Wizard") { }
internal static readonly Wizard _ = new Wizard();
}
}
internal abstract class eItem : EnumType
{
private eItem(int value, string name): base(0, "Apple") { }
// operator overloads like |, &, ^, etc...
//...
internal sealed class Pizza : eItem
{
private Pizza(): base(2, "Pizza") { }
internal static readonly Pizza _ = new Pizza();
}
}
那么你的样本将被重写为:
var myList = new List<EnumType>();
myList.Add(eUnit.Warrior._);
myList.Add(eItem.Pizza._);
var result = myList[0] switch
{
eUnit eUnit => eUnit switch
{
eUnit.Villager villager => DoVillagerStuff(villager),
eUnit.Warrior warrior => DoWarriorStuff(warrior),
eUnit.Wizard wizard => DoWizardStuff(wizard),
_ => throw new InvalidOperationException("Unknonwn eItem");
},
eItem eItem = eItem switch
{
eItem.Pizza pizza => DoPizzaStuff(pizza),
_ => throw new InvalidOperationException("Unsupported eItem")
}
};