const int而不是enum的列表

我开始研究一个大的c#代码库,发现使用了一个带有几个const int字段的静态类。 这个类的行为与枚举完全相同。

我想把这个类转换成一个实际的枚举,但是权力可以说是没有。 我想转换它的主要原因是我可以将枚举作为数据类型而不是int。 这对可读性有很大帮助。

是否有任何理由不使用枚举并使用const int代替? 目前这是代码的方式:

public int FieldA { get; set; } public int FieldB { get; set; } public static class Ids { public const int ItemA = 1; public const int ItemB = 2; public const int ItemC = 3; public const int ItemD = 4; public const int ItemE = 5; public const int ItemF = 6; } 

但是,我认为应该是以下内容:

 public Ids FieldA { get; set; } public Ids FieldB { get; set; } 

我认为这里的许多答案都忽略了enums语义的含义。

  • 当事先知道所有有效值(Ids)的整个集合并且小到足以在程序代码中声明时,您应该考虑使用枚举。

  • 当已知值是所有可能值的子集时,您应该考虑使用int – 并且代码只需要知道此子集。

关于重构 – 当时间和业务约束允许时,当新设计/实现比先前实现具有明显优势并且风险得到充分理解时,清理代码是个好主意。 在利益低或风险高(或两者兼有)的情况下,采取“不伤害”而不是“持续改进”的立场可能更好。 只有您能够判断哪种情况适用于您的情况。

顺便说一句,枚举常量int都不是一个好主意的情况是ID表示外部存储(如数据库)中记录的标识符。 在程序逻辑中对这些ID进行硬编码通常是有风险的,因为这些值在不同的环境中可能实际上是不同的(例如,测试,开发,生产等)。 在这种情况下,在运行时加载值可能是更合适的解决方案。

您建议的解决方案看起来很优雅,但不会按原样运行,因为您不能使用静态类型的实例。 比模拟枚举有点棘手。

为实现选择enum或const-int有几个可能的原因,虽然我不能想到你发布的实际例子有很多强大的 – 从表面看来,它似乎是枚举的理想候选者。

想到的一些想法是:

枚举

  • 它们提供类型安全性。 您不能传递任何需要枚举值的旧数字。
  • 值可以自动生成
  • 您可以使用reflection轻松地在“值”和“名称”之间进行转换
  • 您可以轻松枚举循环中枚举中的值,然后如果添加新的枚举成员,循环将自动将它们考虑在内。
  • 如果您不小心重复了某个值,则可以插入新的enunm值,而不必担心会发生冲突。

常量,整型

  • 如果您不了解如何使用枚举(例如,不知道如何更改枚举的基础数据类型,或者如何为枚举值设置显式值,或者如何将相同的值分配给多个常量),您可能会错误地相信通过使用const,你实现了一些你不能使用enum的东西。
  • 如果你已经习惯了其他语言,你可能会自然地解决问题,而不是意识到存在更好的解决方案。
  • 您可以从类派生来扩展它们,但令人烦恼的是,您无法从现有的枚举中获取新的枚举(这将是一个非常有用的function)。 因此,你可以使用一个类(但不是你的例子!)来实现“可扩展的枚举”。
  • 你可以很容易地通过它。 使用枚举可能需要您不断地将从数据库接收的数据(例如)转换为枚举类型。 你在方便时获得的类型安全损失。 至少在你传出错误号码之前… 🙂
  • 如果使用readonly而不是const,则值将存储在需要时读取的实际内存位置。 这允许您将常量发布到在运行时读取和使用的另一个程序集,而不是内置到另一个程序集中,这意味着当您更改自己程序集中的任何常量时,不必重新编译依赖程序集。 如果您希望能够通过仅释放一个或两个程序集的更新来修补大型应用程序,这是一个重要的考虑因素。
  • 我想这是一种让枚举值必须保持不变的更清晰的方法。 有了枚举,另一个程序员就会毫不犹豫地投入一个新的值,但是一系列的结果让你停下来思考“为什么会这样?我如何安全地添加新值?”。 但是我通过在枚举上添加明确的值并添加明确的注释来实现这一点,而不是诉诸于consts。

为什么要单独执行实施?

  • 这段代码很可能是由一个没有充分理由的白痴写的。 但改变他的代码并向他展示他是一个白痴并不是一个聪明或有帮助的举动。
  • 可能有一个很好的理由就是这样,如果你改变它就会破坏一些东西(例如,它可能需要成为一个类,因为通过reflection访问,通过外部接口暴露,或阻止人们轻松地序列化值,因为他们将被你正在使用的混淆系统打破。 不完全理解某些东西如何工作的人不会在系统中引入不必要的错误,特别是如果他们不知道如何测试他们的变化以确保他们没有破坏任何东西。
  • 该类可以由外部工具自动生成,因此它是您需要修复的工具,而不是源代码。
  • 可能有计划在将来为该课程做更多的事情(?!)
  • 即使改变是安全的,您也必须重新测试受更改影响的所有内容。 如果代码按原样运行,那么收益是否值得痛苦? 在处理遗留系统时,我们经常会看到现有的质量差的代码,或者只是按照我们个人喜欢的方式完成,而且我们必须接受“修复”它并不符合成本效益,无论它有多少琐事。 当然,你也可能会发现自己咬了一口“我告诉你了!” 当基于const的实现由于缺乏类型安全而失败时。 但除了类型安全之外,实现最终不会比枚举更有效或更有效。

如果没有损坏,请不要修理它。

我不知道您正在处理的系统的设计,但我怀疑这些字段是恰好恰好具有许多预定义值的整数。 也就是说,在某些未来状态下,它们可能包含超过这些预定义值。 虽然enum允许该场景(通过强制转换),但它意味着只有枚举包含的值才有效。

总的来说,这种变化是一种语义变化,但它是不必要的。 像这样的不必要的更改通常是错误的来源,额外的测试开销和其他令人头痛的问题,只有轻微的好处。 我说添加评论表示这可能是一个enum并保持原样。

是的,它确实有助于提高可读性,而且我不能想出任何反对它的理由。

使用const int是C ++编程实践的一个非常常见的“旧学校”。

我看到的原因是,如果你想与另一个使用相同常量的系统松散耦合,你可以避免紧密耦合并共享相同的枚举类型。

就像RPC调用或其他东西一样……