简体   繁体   English

const int而不是enum的列表

[英]List of const int instead of enum

I started working on a large c# code base and found the use of a static class with several const ints fields. 我开始研究一个大的c#代码库,发现使用了一个带有几个const int字段的静态类。 This class is acting exactly like an enum would. 这个类的行为与枚举完全相同。

I would like to convert the class to an actual enum, but the powers that be said no. 我想把这个类转换成一个实际的枚举,但权力说不。 The main reason I would like to convert it is so that I could have the enum as the data type instead of int. 我想转换它的主要原因是我可以将枚举作为数据类型而不是int。 This would help a lot with readability. 这对可读性有很大帮助。

Is there any reason to not use enums and to use const ints instead? 是否有任何理由不使用枚举并使用const int代替? This is currently how the code is: 目前这是代码的方式:

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;
}

However, I think it should be the following instead: 但是,我认为应该是以下内容:

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

I think many of the answers here ignore the implications of the semantics of enums . 我认为这里的许多答案都忽略了enums语义的含义。

  • You should consider using an enum when the entire set of all valid values (Ids) is known in advance, and is small enough to be declared in program code. 当事先知道所有有效值(Ids)的整个集合并且小到足以在程序代码中声明时,您应该考虑使用枚举。

  • You should consider using an int when the set of known values is a subset of all the possible values - and the code only needs to be aware of this subset. 当已知值是所有可能值的子集时,您应该考虑使用int - 并且代码只需要知道此子集。

With regards to refactoring - when time and business contraints allow, it's a good idea to clean code up when the new design/implementation has clear benefit over the previous implementation and where the risk is well understood. 关于重构 - 当时间和业务约束允许时,当新设计/实现比先前实现具有明显优势并且风险得到充分理解时,清理代码是个好主意。 In situations where the benefit is low or the risk is high (or both) it may be better to take the position of "do no harm" rather than "continuously improve" . 在利益低或风险高(或两者兼有)的情况下,采取“不伤害”而非“持续改进”的立场可能更好。 Only you are in a position to judge which case applies to your situation. 只有您能够判断哪种情况适用于您的情况。

By the way, a case where neither enums or constant ints are necessarily a good idea is when the IDs represent the identifiers of records in an external store (like a database). 顺便说一句,那里既没有枚举常量是整数的情况下,一定是一个好主意,当这些ID代表的外部存储(如数据库)的记录的标识符。 It's often risky to hardcode such IDs in the program logic, as these values may actually be different in different environments (eg. Test, Dev, Production, etc). 在程序逻辑中对这些ID进行硬编码通常是有风险的,因为这些值在不同的环境中实际上可能是不同的(例如,测试,开发,生产等)。 In such cases, loading the values at runtime may be a more appropriate solution. 在这种情况下,在运行时加载值可能是更合适的解决方案。

Your suggested solution looks elegant, but won't work as it stands, as you can't use instances of a static type. 您建议的解决方案看起来很优雅,但不会按原样运行,因为您不能使用静态类型的实例。 It's a bit trickier than that to emulate an enum. 这比模拟枚举有点棘手。

There are a few possible reasons for choosing enum or const-int for the implementation, though I can't think of many strong ones for the actual example you've posted - on the face of it, it seems an ideal candidate for an enum. 为实现选择enum或const-int有几个可能的原因,虽然我不能想到你发布的实际例子中有很多强大的理由 - 从表面来看,它似乎是枚举的理想候选者。

A few ideas that spring to mind are: 我想到的一些想法是:

Enums 枚举

  • They provide type-safety. 它们提供类型安全性。 You can't pass any old number where an enum value is required. 您无法传递任何需要枚举值的旧数字。
  • Values can be autogenerated 值可以自动生成
  • You can use reflection to easily convert between the 'values' and 'names' 您可以使用反射轻松转换'值'和'名称'
  • You can easily enumerate the values in an enum in a loop, and then if you add new enum members the loop will automatically take them into account. 您可以轻松枚举循环中枚举中的值,然后如果添加新的枚举成员,循环将自动将它们考虑在内。
  • You can insert new enunm values without worrying about clashes occurring if you accidentally repeat a value. 如果您不小心重复了某个值,则可以插入新的enunm值,而不必担心会发生冲突。

const-ints 常量,整型

  • If you don't understand how to use enums (eg not knowing how to change the underlying data type of an enum, or how to set explicit values for enum values, or how to assign the same value to mulitple constants) you might mistakenly believe you're achieving something you can't use an enum for, by using a const. 如果您不了解如何使用枚举(例如,不知道如何更改枚举的基础数据类型,或者如何为枚举值设置显式值,或者如何将相同的值分配给多个常量),您可能会错误地相信你通过使用const实现了一些你不能使用枚举的东西。
  • If you're used to other languages you may just naturally approach the problem with consts, not realising that a better solution exists. 如果你已经习惯了其他语言,你可能会自然而然地用问题解决问题,而不是意识到存在更好的解决方案。
  • You can derive from classes to extend them, but annoyingly you can't derive a new enum from an existing one (which would be a really useful feature). 您可以从类派生来扩展它们,但是令人烦恼的是,您无法从现有的枚举中获取新的枚举(这将是一个非常有用的功能)。 Potentially you could therefore use a class (but not the one i your example!) to achieve an "extendable enum". 因此,你可以使用一个类(但不是你的例子!)来实现“可扩展的枚举”。
  • You can pass ints around easily. 你可以很容易地通过它。 Using an enum may require you to be constantly casting (eg) data you receive from a database to and from the enumerated type. 使用枚举可能需要您不断地将从数据库接收的数据(例如)转换为枚举类型。 What you lose in type-safety you gain in convenience. 您在便利性方面获得的类型安全性损失。 At least until you pass the wrong number somewhere... :-) 至少在你传出错误号码之前... :-)
  • If you use readonly rather than const, the values are stored in actual memory locations that are read when needed. 如果使用readonly而不是const,则值将存储在需要时读取的实际内存位置。 This allows you to publish constants to another assembly that are read and used at runtime, rather than built into the other assembly, which means that you don't have to recompile the dependant assembly when you change any of the constants in your own assembly. 这允许您将常量发布到在运行时读取和使用的另一个程序集,而不是内置到另一个程序集中,这意味着在更改自己程序集中的任何常量时,不必重新编译依赖程序集。 This is an important consideration if you want to be able to patch a large application by just releasing updates for one or two assemblies. 如果您希望通过仅释放一个或两个程序集的更新来修补大型应用程序,这是一个重要的考虑因素。
  • I guess it is a way of making it clearer that the enum values must stay unchanged. 我想这是一种让枚举值必须保持不变的更清晰的方法。 With an enum another programmer will just drop in a new value without thinking, but a list of consts makes you stop and think "why is it like this? How do I add a new value safely?". 有了枚举,另一个程序员就会毫不犹豫地投入一个新的值,但是一系列的结果让你停下来思考“为什么会这样?我如何安全地添加新值?”。 But I'd achieve this by putting explicit values on the enums and adding a clear comment, rather than resorting to consts. 但是我通过在枚举上添加明确的值并添加明确的注释来实现这一点,而不是诉诸于consts。

Why should you leave the implementation alone? 你为什么要单独执行这个实现?

  • The code may well have been written by an idiot who has no good reason for what he did. 这段代码很可能是由一个没有充分理由的白痴写的。 But changing his code and showing him he's an idiot isn't a smart or helpful move. 但改变他的代码并向他展示他是一个白痴并不是一个聪明或有帮助的举动。
  • There may be a good reason it's like that, and you will break something if you change it (eg it may need to be a class due to being accessed through reflection, being exposed through external interfaces, or to stop people easily serializing the values because they'll be broken by the obfuscation system you're using). 这可能是一个很好的理由,如果你改变它就会破坏一些东西(例如,由于通过反射访问,通过外部接口暴露,或者阻止人们轻易地序列化值,它可能需要成为一个类他们将被你正在使用的混淆系统打破。 No end of unnecessary bugs are introduced into systems by people who don't fully understand how something works, especially if they don't know how to test their changes to ensure they haven't broken anything. 不完全理解某些东西如何工作的人不会在系统中引入不必要的错误,特别是如果他们不知道如何测试他们的变化以确保他们没有破坏任何东西。
  • The class may be autogenerated by an external tool, so it is the tool you need to fix, not the source code. 该类可以由外部工具自动生成,因此它是您需要修复的工具,而不是源代码。
  • There may be a plan to do something more with that class in future (?!) 可能有计划在将来为该课程做更多的事情(?!)
  • Even if it's safe to change, you will have to re-test everything that is affected by the change. 即使更改是安全的,您也必须重新测试受更改影响的所有内容。 If the code works as it stands, is the gain worth the pain? 如果代码按原样运行,那么收益是否值得痛苦? When working on legacy systems we will often see existing code of poor quality or just done a way we don't personally like, and we have to accept that it is not cost effective to "fix" it, no matter how much it niggles. 在处理遗留系统时,我们经常会看到现有的质量差的代码,或者只是按照我们个人不喜欢的方式进行,我们必须接受“修复”它并不符合成本效益,无论它有多么麻烦。 Of course, you may also find yourself biting back an "I told you so!" 当然,你也可能会发现自己咬了一口“我告诉你了!” when the const-based implementation fails due to lacking type-safety. 当基于const的实现由于缺乏类型安全而失败时。 But aside from type-safety, the implementation is ultimately no less efficient or effective than an enum. 但除了类型安全之外,实现最终不会比枚举更有效或更有效。

If it ain't broke, don't fix it. 如果没有损坏,请不要修理它。

I don't know the design of the system you're working on, but I suspect that the fields are integers that just happen to have a number of predefined values. 我不知道您正在处理的系统的设计,但我怀疑这些字段是恰好恰好具有许多预定义值的整数。 That's to say they could, in some future state, contain more than those predefined values. 也就是说,在未来某个状态下,它们可能包含超过这些预定义值。 While an enum allows for that scenario (via casting), it implies that only the values the enumeration contains are valid. 虽然enum允许该场景(通过强制转换),但它意味着只有枚举包含的值才有效。

Overall, the change is a semantic one but it is unnecessary. 总的来说,这种变化是一种语义变化,但这是不必要的。 Unnecessary changes like this are often a source of bugs, additional test overhead and other headaches with only mild benefits. 像这样的不必要的变化通常是错误的来源,额外的测试开销和其他令人头疼的问题,只有轻微的好处。 I say add a comment expressing that this could be an enum and leave it as it is. 我说添加评论表示这可能是一个enum并保持原样。

Yes, it does help with readability, and no I cannot think of any reason against it. 是的,它确实有助于提高可读性,而且我无法想出任何反对它的理由。

Using const int is a very common "old school" of programming practice for C++. 使用const int是C ++编程实践中非常常见的“旧学校”。

The reason I see is that if you want to be loosely coupled with another system that uses the same constants, you avoid being tightly coupled and share the same enum type. 我看到的原因是,如果你想与另一个使用相同常量的系统松散耦合,你可以避免紧密耦合并共享相同的枚举类型。

Like in RPC calls or something... 就像在RPC调用中那样......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM