我想使用标志枚举作为过滤器来过滤单个值枚举。
当我使用一个标志枚举来提供两者时,我有两个异议:
命名约定状态比标志枚举是复数,而单个项目枚举不是;
我希望filter / flags枚举的值为" none"和"所有",但在不用作过滤器时这些值不是有效值;
说明我的意图的一个例子(但是由于两个枚举之间的类型不兼容而无法正常运行)
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来在两个枚举之间进行转换。但是应该有更优雅,更杂乱的方式来做到这一点,对吗?
[丹尼斯回答后编辑] 我确实考虑过使用集合作为过滤器。此外,它感觉重量大,需要更多的代码,而使用枚举是轻量级的。然而,当我没有完成这项工作时,我没有任何用户,轻盈/优雅与否......
[标记为ansered后编辑] 谢谢大家的投入!
答案 0 :(得分:0)
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)))
{
// ...
}
答案 1 :(得分:0)
你有2个解决方案:
首先:
Material value = (Material)Enum.Parse(typeof (Material), Materials.wood.ToString());
即。转换枚举
第二:仅使用Materials枚举。不清楚但很简单。
答案 2 :(得分:0)
最佳方式是使用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
}