【问题标题】:Correct way to initialize Enums inside a class constructor在类构造函数中初始化枚举的正确方法
【发布时间】:2011-10-06 00:04:36
【问题描述】:

我可能以错误的方式看待枚举,但想确保我对如何使用它们有正确的理论。

假设我们有一个名为 Colour 的枚举。

enum Colour { Red, Green, Blue };

红色 绿色和蓝色由 0-255 个值表示。 我正在尝试在类形状中初始化此枚举,但我不确定如何去做。

public class Shape
{

    Colour colour;

    public Shape(Colour c)
    {
         //Some attempts at initialization.


         //Treating It like an object
         this.colour = 
            c{
                255,255,255
            };

         //Again
         this.colour.Red = c.Red
         this.colour.Blue = c.Blue
         this.colour.Green = c.Green

         Colour.red = c.red?


         }
    }
}

就我对枚举的看法而言,我可能还差得很远。谁能指点一下?

【问题讨论】:

    标签: c# enums initialization


    【解决方案1】:

    在这种情况下,您可能希望 Color 为 struct 而不是枚举。在 C# 中,枚举是单值构造,但您有三个值(红色、绿色和蓝色)。以下是我可能会做的事情:

    public struct Colour 
    {
        private byte red;
        private byte green;
        private byte blue;
    
        public Colour(byte r, byte g, byte b) 
        {
            this.red = r;
            this.green = g;
            this.blue = b;
        }
    }
    
    public class Shape
    {
        public Colour Colour { get; private set; }
    
        public Shape(Colour c)
        {
            this.Colour = c;
        }
    }
    

    然后当您创建形状对象时:

    var shape = new Shape(new Colour(203, 211, 48));
    

    编辑:正如 Chris 在 cmets 中指出的那样,您可以简单地使用框架提供的 System.Drawing.Color 结构。上面的例子可以简化为:

    using System.Drawing;
    
    public class Shape
    {
        public Color Colour { get; private set; }
    
        public Shape(Color c)
        {
            this.Colour = c;
        }
    }
    
    var shape = new Shape(Color.FromArgb(203, 211, 48));
    

    【讨论】:

    • 如果不感兴趣,为什么不使用 Color 类?这似乎具有相同的功能,然后更多,并且将更具互操作性,更不像重新发明轮子......
    • @Chris:这是一个很好的观点,我认为你是对的。我已经使用内置的 System.Drawing.Color 结构更新了我的答案。
    【解决方案2】:

    枚举非常类似于关系数据库中的类型(或关联)表。它是一组选项列表,因此您可以限制一个值。如果您不熟悉关系数据库,则可能将枚举视为“选择列表”。枚举为我们提供了一个小的、有限的变量选择列表,而底层类型(int、byte 等)要大得多。

    完成您尝试的常规方法是测试枚举值,然后设置您的对象:

    switch(c)
    {
       case Colour.Red:
            //Set up red shape here
            break;
       //etc ...
    }
    

    【讨论】:

    • adenum:实际上,您可以为枚举指定底层类型 (enum MyEnum : int16 {...}),但不鼓励这样做(有关详细信息,请参阅 msdn 关于枚举)。当您不指定值时,您的枚举成员会自动获得 int 值 0、1、2、...)(例外:“flags”枚举以 1、2、4、...开头)
    • @eFloh:在示例中,我有明确的 1,2,4 ... n 值的编码标志,但这仅仅是为了明确显示框架隐式执行的操作。这是教授位掩码如何工作的好方法。 ;-) 但是,在业务代码中,我同意 100%。我想不出在枚举上设置数字的理由(并不是说没有任何正当理由,只是没有我能想到的)。
    • 哦,在枚举上设置数字的一个简单原因:考虑拥有一个发送某种数字返回码的 Web 服务。您可以使用已知代码在本地定义一个枚举,以便能够编写不言自明的代码(例如 ´if ((WsCode)wsResultcode == WsCode.NoDataFound) { ...}`)但是当您控制服务定义时,您绝对应该直接使用枚举值,并记住 WSDL 枚举携带它们的值,而只有名称,因此“通过 Web 服务强制转换为 int”是个坏主意。 .
    • @eFloh:赞。我喜欢这个主意。在我添加评论时并没有考虑 SOA。谢谢。
    【解决方案3】:
    this.colour = Colour.Red; // or Colour.Green or whatever
    

    this.colourColour 类型,只能取三个值之一。将Colour 视为类似Integer 的类型,但它只能采用三个值之一,而Integer 可以采用Integer.MIN_VALUE..Integer.MAX_VALUE 范围内的任何一个值。

    如果您尝试从中构造RGB 颜色,那么这不是正确的方法。在这种情况下,您正在寻找一个名为 Colour 的类,它的 red, green and blue 组件具有不同的值。

    【讨论】:

      【解决方案4】:

      您的枚举Colour 没有您定义的每个枚举值的属性。 Red、Green 和 Blue 的值是您的枚举可能是的值。

      您想要执行类似this.colour = Colour.Red 的操作,将您的colour 变量设置为红色值。然后,稍后在代码中,如果您只想根据值是否为红色来触发一些代码,您可以执行以下操作:

      if(this.colour == Colour.Red)
      {
      // Do red specific logic
      }
      

      【讨论】:

        【解决方案5】:

        最好使用不可变结构:

        public struct Colour
        {
            private readonly byte red;
        
            private readonly byte green;
        
            private readonly byte blue;
        
            public Colour(byte red, byte green, byte blue)
            {
                this.red = red;
                this.green = green;
                this.blue = blue;
            }
        
            public byte Red
            {
                get
                {
                    return this.red;
                }
            }
        
            public byte Green
            {
                get
                {
                    return this.green;
                }
            }
        
            public byte Blue
            {
                get
                {
                    return this.blue;
                }
            }
        }
        

        你可以这样初始化它:

        Shape shape = new Shape(new Colour(104, 255, 67));
        

        【讨论】:

          【解决方案6】:

          如果颜色是您的枚举,那么您在构造函数中需要做的就是说:

          this.colour = c;
          

          但是,您对“红色绿色和蓝色由 0-255 值表示”的评论让我有点困惑和担心。大多数颜色都会为红色绿色和蓝色中的每一个都有一个值,所以你不想要一个枚举。

          通过类比下拉框可以很容易地想到枚举。有一组固定值,您的选择必须是其中一个,而不是其他。下拉列表背后可能有一个值,但通常您只是想知道下拉列表是否显示“红色”,而不是它背后的值是什么。这样做的原因是,通常使用 Enums 你只会说“If (color=Colour.Red) then....”。

          您正在做的事情听起来更像是 .NET 类颜色(由美国人命名,如果这是您想要的,这可能就是您找不到它的原因)。这具有 R、G、B 的属性以及一组静态属性,这些属性将返回 Color 类的预定义实例(例如 Color.Red),将返回具有适当 RGB 集的 Color 实例。

          所以我认为你可能在 Enums 上搞错了,可能你想要的是 Color 类。

          您可能最不想做的就是拥有某种 Factory 类,它可以执行以下操作:

          public Color CreateColor(Colour colEnum)
          {
              switch(colEnum)
              case Colour.Red:
              return Color.Red;
              etc.
          }
          

          (对于混淆名称和使用颜色和颜色表示歉意)

          这可以确保您根据您的枚举获得颜色,并且只有在您的枚举中定义的颜色才能以这种方式创建。

          【讨论】:

            【解决方案7】:

            也许 type-safe 枚举是您正在寻找的。它们允许比标准枚举更丰富的行为。

            public sealed class Colour
            {
              public int RedComponent { get; private set;}
              public int GreenComponent { get; private set;}
              public int BlueComponent { get; private set;}
            
              public static readonly Colour Red = new Colour(255,0,0);
            
              private Colour(int red, int green, int blue)
              {
                RedComponent = red;
                GreenComponent = green;
                BlueComponent = blue;
              }
            }
            

            然后你可以有一个方法Foo(Colour c){//Do something with c.RedComponent etc.} 并调用Foo(Colour.Red)

            您甚至可以按照普通枚举比较值:

            Bar(Colour c)
            {
              return c == Colour.Red;
            }
            

            【讨论】:

            • 如果您想要自定义颜色,您可以公开构造函数,但是在这种情况下 new Colour(255,0,0) == Colour.Red 将返回 false,因为它们会指向不同的实例。
            猜你喜欢
            • 2012-09-15
            • 2021-08-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-07-27
            相关资源
            最近更新 更多