我將這些多個列舉用作 Id 并希望在單個串列中使用它們。
public enum eUnit
{
Villager,
Warrior,
Wizard,
}
public enum eVehicle
{
Car,
Train,
Helicopter,
}
public enum eItem
{
Apple,
Steak,
Pizza,
}
像下面的代碼一樣嗎?
List<?enum?> myList = new List<?enum?>();
myList.Add(eUnit.Warrior);
myList.Add(eItem.Pizza);
if(myList[0].GetType() == typeof(eUnit))
DoStuff();
...
...
uj5u.com熱心網友回復:
另一種方法是通過OneOf庫使用可區分的聯合。
var myList = new List<OneOf<eUnit, eVehicle, eItem>>()
{
eUnit.Warrior, eVehicle.Car
};
myList[0].Switch(
unit => Console.WriteLine("Unit"),
vehicle => Console.WriteLine("Vehicle"),
item => Console.WriteLine("Item")
);
我做了一個樣品
uj5u.com熱心網友回復:
您可以嘗試使用動態型別。也許這有點矯枉過正,但這取決于你。
uj5u.com熱心網友回復:
您可以實作自己的List<T>. 這是一個簡單的例子:
public class EnumList
{
private readonly List<Entry> _entriesList = new List<Entry>();
public object this[int index]
{
get
{
var item = _entriesList[index];
return Enum.Parse(item.Key, item.Value);
}
set
{
_entriesList[index] = new Entry(value.GetType(), value.ToString());
}
}
private class Entry
{
public Type Key { get; set; }
public string Value { get; set; }
public Entry(Type key, string value)
{
Key = key;
Value = value;
}
}
public void Add<TEnum>(TEnum item) where TEnum : struct, Enum
{
_entriesList.Add(new Entry(typeof(TEnum), item.ToString()));
}
public List<TEnum> Get<TEnum>() where TEnum : struct, Enum
{
return _entriesList.Where(x => x.Key == typeof(TEnum)).Select(x => Enum.TryParse(x.Value, out TEnum result) ? result : default).ToList();
}
public bool Exists<TEnum>(TEnum item) where TEnum : struct, Enum
{
return _entriesList.Any(x => x.Key == typeof(TEnum) && x.Value == item.ToString());
}
}
用法 :
var list = new EnumList();
list.Add(eUnit.Warrior);
list.Add(eItem.Pizza);
list.Add(eVehicle.Car);
list.Add(eVehicle.Helicopter);
list.Add(eUnit.Villager);
list.Add(eItem.Apple);
if((eUnit)list[0] == eUnit.Warrior || list.Exists(eUnit.Villager))
{
// do stuff
}
這只是一個幫助您實作自己的示例,請記住,您應該始終嘗試通過指定預期的enums來縮小可接受的引數范圍,盡管您可以完全通用。
uj5u.com熱心網友回復:
正如安德烈提到的,使用識別聯合,如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")
}
};
uj5u.com熱心網友回復:
你可以看看這個ArrayList類:
public enum eUnit
{
Villager,
Warrior,
Wizard,
}
public enum eVehicle
{
Car,
Train,
Helicopter,
}
public enum eItem
{
Apple,
Steak,
Pizza,
}
void Main()
{
var myList = new ArrayList();
myList.Add(eUnit.Warrior);
myList.Add(eItem.Pizza);
for (int i = 0; i < myList.Count; i )
{
var element = myList[i];
if (element is eUnit unit)
Console.WriteLine($"Element at index {i} is eUnit {unit}");
else if (element is eVehicle vehicle)
Console.WriteLine($"Element at index {i} is eVehicle {vehicle}");
else if (element is eItem item)
Console.WriteLine($"Element at index {i} is eItem {item}");
else
Console.WriteLine($"Element at index {i} is another type");
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/330737.html
