【问题标题】:Enums and Constants. Which to use when?枚举和常量。什么时候用?
【发布时间】:2010-10-11 11:02:57
【问题描述】:

我在阅读枚举时发现它们与声明常量非常相似。我怎么知道何时使用常量而不是枚举,反之亦然。使用枚举有哪些优点?

【问题讨论】:

标签: c# language-agnostic enums


【解决方案1】:

当您想定义某个值的范围时,请使用枚举。颜色是一个明显的例子:

public enum Colour
{
    White,
    Red,
    Blue
}

或者可能是一组可能的事情,例如: (例如我偷了here,因为我很懒)

[FlagsAttribute]
enum DistributedChannel
{
  None = 0,
  Transacted = 1,
  Queued = 2,
  Encrypted = 4,
  Persisted = 16,
  FaultTolerant = Transacted | Queued | Persisted
}

常量应该用于单个值,例如 PI。没有 PI 值的范围,只有 PI。

其他需要考虑的点是:

  • a:常量不一定表示常量之间的关系,而枚举表示某些东西可以是枚举定义的集合之一。
  • b:定义的枚举在用作参数时可以帮助您进行类型检查。常量只是值,因此它们不提供任何额外的语义信息。

【讨论】:

  • 如果你最终在枚举上大量使用.ToString(),使用一个看起来和行为都像枚举但绕过对ToString()的调用的const字符串有什么价值? Example
  • 等等,我想我已经回答了我自己的问题。该示例中的代码不起作用:您必须将输入作为字符串,这实际上不像枚举。
  • 为什么你不能只拥有一个颜色不变的静态类 Color 而不是枚举呢?有什么区别?
  • 简短声明Type Safety"
  • [FlagsAttribute] 示例的链接已损坏。
【解决方案2】:

其他答案中缺少的是枚举具有整数基类型。您可以将默认值从 int 更改为除 char 之外的任何其他整数类型,例如:

enum LongEnum : long {
    foo,
    bar,
}

您可以显式地转换和隐式地转换到基类型,这在 switch 语句中很有用。请注意,即使枚举没有具有适当值的成员,也可以将基类型的任何值强制转换为枚举。因此,始终在开关中使用默认部分是一个好主意。顺便说一句,.NET 本身甚至允许浮点值枚举,但你不能在 C# 中定义它们,尽管我认为你仍然可以使用它们(除了在 switch 中)。

此外,使用枚举可以提高类型安全性。如果您打算使用例如int 常量作为方法参数,然后我可以使用任何 int 值调用该方法。当然,通过强制转换它也可以在枚举中发生,但它不会意外发生。更糟糕的是可能会混淆参数的顺序。

void method(int a, int b) {...}

如果常量 A 只能进入 a,而常量 B 只能进入 b,那么使用两种不同的枚举类型将发现编译期间的任何误用。

【讨论】:

    【解决方案3】:

    常量是一种语言特性,它表示在枚举是特定类型的情况下,变量不会改变值(因此编译器可以围绕该知识进行优化)。

    常量可以是任何数据类型,但枚举就是枚举。

    我在可以有多个选项并希望提高代码可读性的任何地方都使用枚举。即,您可以将跟踪级别作为值为 0、1、2 的 int 或作为错误、警告和信息的枚举。

    枚举还可以用作按位运算符,即 FontStyle.Bold | FontStyle.Italic 会给你粗体和斜体字体。

    【讨论】:

      【解决方案4】:

      除了罗伯特的回答:

      1. 对一组有限的命名值使用枚举。您并不真正关心每个符号背后的数值(但您仍然可以强加它们,例如为了与旧系统兼容)。

      2. Robert:是的,Enum 可以用作位域。使用Flags 属性(并确保枚举成员具有合适的数值)。

      【讨论】:

        【解决方案5】:

        C# 常量与变量的相似之处在于它为值提供了定义的名称。但是,常量与标准变量不同,因为一旦定义,分配给常量的值就永远无法更改。常量的主要好处是它们有助于创建自记录代码以及允许在单个位置声明键值,如果需要更新值和重新编译软件,则可以轻松维护。

        而枚举器列表对于定义序列和状态很有用,尤其是当这些状态有自然进展时。这是因为列表中的每个常量都可以使用其名称或值进行格式化和比较。枚举也可用于定义一组有限的有效值。

        【讨论】:

          【解决方案6】:

          在使用enum 而不是const 时,我发现很方便的一件事是您可以遍历enum 中的值,而使用const 值更难做到这一点。

          【讨论】:

            【解决方案7】:

            如果您需要基于整数的值,请使用枚举。 如果您需要基于字符串的值,请使用带有常量的结构。

            当你有类似的东西时

            class x
            {
                public string string_value {get;set;}
                publi int int_value  {get;set;}
            }
            
            x model = new x();
            model.string_value  = struct.some_value;
            model.int_value = enum.some_value;
            

            【讨论】:

              【解决方案8】:
              If you have a set of predefined choices which is not supposed to change (i.e adding more choices etc.) than use enum otherwise consts. Consider the following:
              public class Math
              {
                  enum Command {none = 0, add =1, subtract = 2} 
                  const int none =0, add=1,subtract =2;
                  public virtual int Operate(int a, int b, Command command) 
                  {
                      if (command == Command.add) return a+b;
                      if(command == Command.subtract) return a-b;
                      return a;
                  }
                  public virtual int Operate(int a, int b, int command) 
                  {
                      if (command == add) return a+b;
                  if(command==subtract) return a-b;
                      return a;
                  }
              }`
              
              class Math1: Math
              {
                  public override Operate(int a, int b, int command)
                  {
                      if(command<3) return base.Operate(a, b, command)
                      if(command =3) return a*b;
                      if(command==4) return a/b;
                      return a;
                  }
              }
              

              所以使用 const 可以让您传递未在 const 声明中定义的参数值,即 3 用于乘法,4 用于除法。这是好是坏取决于您的逻辑,有时允许用户传递任意值并收到意外结果是不明智的。

              【讨论】:

                猜你喜欢
                • 2011-03-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-10-22
                相关资源
                最近更新 更多