【问题标题】:Flags enum vs. HashSet of regular enum标记枚举与常规枚举的 HashSet
【发布时间】:2012-01-31 09:55:43
【问题描述】:

是否有令人信服的理由在常规枚举的 HashSet 上使用 Flags 枚举(即位掩码)?据我所知,两者都解决了同样的问题:

enum Color { Red, Green, Blue }

[Flags()]
enum Colors { None = 0, Red = 1, Green = 2, Blue = 4 }

void Test()
{
    // initialization
    var supportedColors1 = new HashSet<Color> { Color.Red, Color.Green };
    var supportedColors2 = Colors.Red | Colors.Green;

    // comparison
    if (supportedColors1.Contains(Color.Green)) { /* ... */ }
    if ((supportedColors2 & Colors.Green) != 0) { /* ... */ }

    // manipulation
    supportedColors1.Remove(Color.Red);
    supportedColors2 ^= Colors.Red;  // if I'm sure that Red is contained
    supportedColors2 &= ~Colors.Red; // if I'm not sure
}

这可能是一个品味问题,但对于没有硬件或系统级位翻转背景的人(= 我的同事),我认为 Set 选项更具可读性。当需要微优化(更好的性能、更少的内存)或 P/Invoking Windows API 时,我可以看到 Flags 选项的优势,但对于标准的业务线数据库应用程序,我很想选择 Set 选项为了可读性。

Flags 选项是否有一些我遗漏的优点,并且可以证明在“常规”代码中使用它是合理的?

【问题讨论】:

    标签: c# .net coding-style enums


    【解决方案1】:

    Flags 选项是否有一些我错过的优点

    除了它们的效率几个数量级之外?这可能与您无关,但它是如此明显的优化,通常是有意义的。

    此外,如果您不喜欢位操作语法(我不怪您),请尝试定义扩展方法来封装它们。但我认为任何称职的程序员,无论他们的背景如何,无论如何都绝对需要了解常见的位操作。如果你的同事被这种用法难住了,那你就有大问题了。

    【讨论】:

    • 我想我应该介入并在这里为我的同事辩护:他们是出色的开发人员,但他们已经在 VBA 和 .NET 中开发 LOB 应用程序多年,不需要位操作,所以理解 a &amp;= ~b 肯定需要比a.Remove(b) 长一点。
    • @Heinzi 不幸的是,我认为这是站不住脚的。这只是一项基本技能,就像用刀做厨师一样,即使你有搅拌机。
    • 量化效率声明:我已经测量了在 .NET 5.0 上找到具有 20 个成员的枚举的最后一个值,分别为 1.0x、0.5x 和 0.01x,用于 List、HashSet 和标志。 2021 年达到 400 个。
    【解决方案2】:

    如您所知,您可以通过这两种方法实现相同的效果。如果要存储来自数据库的数据,使用 HashSet 可能是更好的选择,在性能方面不会有任何明显的差异。 当然,您最终会得到一个更可用(和可读)的代码,以及一个更“适合”您想要整理的数据的类型。在这两种情况下,您都将迭代或检查容器中是否存在值。虽然 Hashset 带有列表的所有典型扩展(包含等),但您必须自己实现这些功能(例如使用自定义扩展方法)。结果将是开发速度放缓和代码可读性降低(对于您的同事:) 没有任何类型的改进。 Here's a good overview about Enum flags

    【讨论】:

    • 我不认为您对数据库存储的评论是正确的。你能详细说明吗?其余的也很脆弱。实现扩展方法既简单又快速,您只需执行一次。之后不会有“可读性较差的代码”——它与使用 HashSet 相同。
    • 嗨,是的,问题是关于数据库驱动的应用程序,所以假设我们从数据库中获取数据集,我们需要将其存储在某个地方以便对其进行排序/过滤,我认为最快(和常见的做法)解决方案是使用某种类型的通用集合。结果是一样的,性能也是一样的(hashset表现不错),而且你不用自己实现Hashset支持的所有扩展方法的麻烦。
    • 如果没有明显的好处,重用已经实现的东西肯定比自己重写要快。另一点是大多数开发人员(如果您在团队中工作)熟悉列表及其方法而不是 Enum 标志。
    【解决方案3】:

    HashSet 解决方案可能运行良好,但效率问题除外。但我认为开发人员应该尽可能地编写正确的代码,而不是尽可能地(被其他同事)接受......如果有人不够熟练,无法理解你清晰正确的解决方案,你不需要付钱为此。

    【讨论】:

      猜你喜欢
      • 2021-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-17
      • 2012-09-16
      • 1970-01-01
      • 2013-03-13
      相关资源
      最近更新 更多