const int的列表,而不是enum

本文关键字:enum int 列表 const | 更新日期: 2023-09-27 18:07:55

我开始在一个大型c#代码库上工作,发现使用带有几个const int字段的静态类。该类的行为与enum完全相同。

我想将类转换为实际的enum,但是他说不。我想转换它的主要原因是这样我就可以将enum作为数据类型而不是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; }

const int的列表,而不是enum

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

  • 当所有有效值(id)的整个集合提前已知时,应该考虑使用枚举,并且枚举足够小,可以在程序代码中声明。

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

关于重构——在时间和业务约束允许的情况下,当新的设计/实现比以前的实现有明显的好处,并且风险已经被很好地理解时,清理代码是一个好主意。在收益低或风险高(或两者兼而有之)的情况下,最好采取"无害"的立场,而不是"持续改进"。只有你才能判断哪种情况适合你的情况。

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

您建议的解决方案看起来很优雅,但无法正常工作,因为您不能使用静态类型的实例。模拟enum要比这复杂一些。

选择enum或const-int来实现有几个可能的原因,尽管我不能为你发布的实际示例想出很多强有力的理由-从表面上看,它似乎是enum的理想候选者。

我想到的一些想法是:

枚举

    它们提供类型安全。在需要枚举值的地方不能传递任何旧数字。
  • 值可以自动生成
  • 您可以使用反射轻松地在"值"answers"名称"之间进行转换
  • 你可以很容易地在循环中枚举枚举枚举中的值,然后如果你添加新的枚举成员,循环将自动考虑它们。
  • 您可以插入新的枚举值,而不必担心如果意外重复一个值会发生冲突。

const-ints

  • 如果你不知道如何使用枚举(例如,不知道如何改变枚举的底层数据类型,或如何为枚举值设置显式值,或如何将相同的值分配给多个常量),你可能会错误地认为,通过使用const,你可以实现一些不能使用枚举的东西。
  • 如果你习惯了其他语言,你可能会很自然地用const来解决问题,而没有意识到存在更好的解决方案。
  • 你可以从类中派生来扩展它们,但恼人的是你不能从一个现有的枚举中派生一个新的枚举(这将是一个非常有用的特性)。因此,你可能会使用一个类(但不是你的例子中的那个!)来实现一个"可扩展枚举"。
  • 你可以很容易地传递整型。使用枚举可能需要不断地将(例如)从数据库接收到的数据转换为枚举类型。在类型安全中失去的,将在方便性中得到。至少在你把号码打错之前……: -)
  • 如果您使用只读而不是const,则值存储在需要时读取的实际内存位置。这允许您将在运行时读取和使用的常量发布到另一个程序集,而不是内建到另一个程序集,这意味着当您更改自己的程序集中的任何常量时,您不必重新编译依赖程序集。如果你想通过发布一个或两个程序集的更新来修补大型应用程序,这是一个重要的考虑因素。
  • 我想这是一种更清楚的方式,枚举值必须保持不变。对于枚举,其他程序员会不假思索地输入一个新值,但是const列表会让你停下来思考"为什么会这样?"如何安全地添加新值?但是我会通过在枚举上添加显式值并添加明确的注释来实现这一点,而不是诉诸于const。

为什么不去管它的实现?

    这段代码很可能是一个白痴写的,他所做的事情没有很好的理由。但是改变他的代码,告诉他他是一个白痴,这不是一个聪明或有益的举动。
  • 这样做可能有一个很好的理由,如果你改变它,你会破坏一些东西(例如,它可能需要是一个类,因为通过反射访问,通过外部接口暴露,或者阻止人们容易序列化值,因为它们会被你正在使用的混淆系统破坏)。由于人们不完全了解某些东西是如何工作的,特别是如果他们不知道如何测试他们的更改以确保他们没有破坏任何东西,就会给系统引入无休止的不必要的bug。
  • 类可以由外部工具自动生成,所以需要修复的是工具,而不是源代码。
  • 将来可能会有一个计划来做更多的事情(?!)
  • 即使更改是安全的,您也必须重新测试受更改影响的所有内容。如果代码可以正常工作,那么付出的代价值得吗?当我们在遗留系统上工作时,我们经常会看到现有的代码质量很差,或者只是以我们个人不喜欢的方式完成,我们必须接受"修复"它是没有成本效益的,不管它有多琐碎。当然,当基于const的实现由于缺乏类型安全而失败时,您也可能会发现自己在"我告诉过你!"但是除了类型安全之外,其实现的效率和效果并不亚于enum。

没坏就别修

我不知道你正在使用的系统的设计,但我怀疑字段是碰巧有一些预定义值的整数。也就是说,在未来的某个状态下,它们可能包含比这些预定义值更多的值。虽然enum允许这种情况(通过强制转换),但它意味着只有枚举包含的值是有效的。

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

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

使用const int是c++编程实践中非常常见的"老派"做法。

我看到的原因是,如果您希望与使用相同常量的另一个系统松散耦合,则避免紧耦合并共享相同的enum类型。