【问题标题】:C# combining single value enum with flags enumC#将单值枚举与标志枚举结合起来
【发布时间】:2015-11-30 13:34:08
【问题描述】:

我想使用标志枚举作为过滤器集来过滤单个值枚举。

当我使用一个标志枚举来提供两者时,我有两个反对意见:

  • 命名约定规定标志枚举是复数,而单个项目枚举不是;

  • 我希望过滤器/标志枚举具有“无”和“全部”的值,但这些值在不用作过滤器时不是有效值;

说明我的意图的示例(但由于两个枚举之间的类型不兼容而无法正常运行)

    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 枚举感觉不好,因为 none 和 all 都不是文章完成的有效值。

我可以使用一些转换为 int 来在两个枚举之间进行转换。但是应该有一种更优雅、更整洁的方式来做到这一点,对吧?

[丹尼斯回答后编辑] 实际上,我确实考虑过使用集合作为过滤器。而且感觉很重,需要更多代码,而使用枚举是轻量级的。但是,什么时候不做我没有用户的工作,轻量级/优雅与否......

[标记为ansered后编辑] 谢谢大家的意见!

【问题讨论】:

    标签: c# enums


    【解决方案1】:

    最佳方式是使用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】:

    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)))
    {
        // ...
    }
    

    【讨论】:

      【解决方案3】:

      您有 2 个解决方案:

      第一:

      Material value = (Material)Enum.Parse(typeof (Material), Materials.wood.ToString());
      

      即转换枚举

      第二:仅使用 Materials 枚举。不清楚但简单。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多