[英]C# combining single value enum with flags enum
我想將標志枚舉用作過濾器集,以對單個值枚舉進行過濾。
當我使用一個標志枚舉來同時提供兩者時,我有兩個反對意見:
命名約定規定,標志枚舉數是復數,而單個項枚舉不是。
我希望過濾器/標志枚舉具有“無”和“全部”的值,但是當不用作過濾器時這些值不是有效值;
說明我的意圖的示例(但由於兩個枚舉之間的類型不兼容而無法正常運行)
enum Material
{
wood,
metal,
plastic
}
[Flags]
enum Materials
{
none = 0,
wood = 1,
metal = 2,
plastic = 4,
all = 7
}
var filter = Materials.all;
foreach (article in articles.Where(a => Filter.HasFlag(a.FinishMaterial))
...
如前所述,該示例無法滿足我的要求。 只使用Materials枚舉是不對的,因為沒有一個和所有的都不是文章完成的有效值。
我可以使用一些強制轉換為int在兩個枚舉之間進行轉換。 但是應該有一種更優雅,更整潔的方式來做到這一點,對嗎?
[丹尼斯回答后編輯]實際上,我確實考慮過使用集合作為過濾器。 同時感覺很重,需要更多代碼,而使用枚舉則是輕量級的。 但是,當is不能完成任務時,我沒有用戶使用它,無論lightweigt / elegant ...
[標記為回復后的編輯]謝謝大家的投入!
IMO使用集合來保存過濾器比操作標志要容易得多且可讀性強:
// This is equivalent of "var filter = Materials.all";
// an empty collection is equivalent of "Materials.None"
var filter = (Material[])Enum.GetValues(typeof(Material));
// use next line, if you need to modify the filter:
// var filter = ((Material[])Enum.GetValues(typeof(Material))).ToList();
foreach (article in articles.Where(a => filter.Contains(a.FinishMaterial)))
{
// ...
}
最佳方法是使用int
轉換而不是Enum.Parse
。 若要解決HasFlag
的問題,可以創建一個擴展方法。 下面是帶有測試的代碼
[TestClass]
public class MaterialsTests
{
[TestMethod]
public void Contains_wroks_as_expected()
{
var filter = Materials.all;
Assert.IsTrue(filter.Contains(Material.metal));
}
}
public static class Extensions
{
public static bool Contains(this Materials filter, Material material)
{
var valueToFilter = (Materials)(int)(material);
return filter.HasFlag(valueToFilter);
}
}
public enum Material
{
wood = 1,
metal = 2,
plastic = 4
}
[Flags]
public enum Materials
{
none = 0,
wood = 1,
metal = 2,
plastic = 4,
all = 7
}
您有2個解決方案:
第一:
Material value = (Material)Enum.Parse(typeof (Material), Materials.wood.ToString());
即轉換枚舉
第二:僅使用材料枚舉。 不清楚但很簡單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.