【问题标题】:Enumeration and constants枚举和常量
【发布时间】:2009-02-05 23:32:14
【问题描述】:

有没有比将枚举声明为更好的方法

public enum DepthNumberSize
{
   Bit1 = 1,
   Bit4 = 4,
   Bit8 = 8,
   Bit16 = 16,
   Bit32 = 32
}

以及每次对相关数据块执行switch语句的操作时,如:

switch(size)
{
    case DepthNumberSize.Bit1:
       buffer[i++] = input[j] & 1;
       buffer[i++] = (input[j] >> 1) & 1;
       // cut
    case DepthNumberSize.Bit8:
       buffer[i++] = input[j++];
       break;
    case DepthNumberSize.Bit16:
       buffer[i++] = input[j] | (input[j] << 8);
       j += 2;
       break;
    // cut
}

?

谢谢。

【问题讨论】:

  • 这个枚举实现了什么?为什么不直接写 16 而不是 DepthNumberSize.Bit16?
  • 枚举正在阻止使用幻数。 “1”表示一个,“Bit1”表示“第一位”。这是有道理的。
  • @AR,我正在尝试重构它。我考虑过使用整数,但开关看起来更丑:-)

标签: design-patterns enums constants


【解决方案1】:

你可以这样做:

    interface IBitSize
    {
        object DoStuff();
    }

    class Bit1 : IBitSize
    {
        public object DoStuff()
        {
            buffer[i++] = input[j] & 1;
            buffer[i++] = (input[j] >> 1) & 1;
            return something.
        }
    }

    class Bit2 : IBitSize
    {
        public object DoStuff()
        {
           //Do different stuff here.
        }
    }

那么你可以这样称呼它:

    IBitSize size = new Bit1();
    size.DoStuff();

这样你就可以去掉开关了。

【讨论】:

    【解决方案2】:

    您可以考虑改用类,可能使用工厂方法来返回正确的大小具体类型,例如

    abstract class BitManipulator
    {
        public abstract void Manipulate(
            byte[] buffer, byte[] input, ref int i, ref int j);
    
        public static BitManipulator Create(int size)
        {
            switch (size)
            {
                case 1: return new Bit1Manipulator();
                case 2: return new Bit2Manipulator();
                // etc.
            }
        }
    }
    
    class Bit1Manipulator : BitManipulator
    {
        public override void Manipulate(
            byte[] buffer, byte[] input, ref int i, ref int j)
        {
            buffer[i++] = input[j] & 1;
            buffer[i++] = (input[j] >> 1) & 1;
        }
    }
    
    // etc. for other classes
    

    然后您就得到了一个 switch 语句,然后所有逻辑都可以包含在特定于大小的类中,而不是在其余代码中通过 switch 语句乱扔垃圾。当然,您可以为每种需要做的事情使用多种方法。

    很难说这是否适合您的应用程序,因为没有很多上下文,但这是可以在这种情况下使用的另一种方法。

    【讨论】:

      【解决方案3】:

      我认为您可能需要澄清一下您的问题。

      但是,您可以通过将枚举转换为字节(枚举的默认类型)来获取枚举的基础值。

      (byte)DepthNumberSize.Bit8
      

      将返回 8。这会更好,因为您实际上会使用您为枚举提供的自定义值(它们默认为 0、1、2 等)。它甚至可以让你摆脱整个 switch 语句,让你编写一个通用代码块,使用枚举变量“size”的底层值来产生所需的结果。

      【讨论】:

        【解决方案4】:

        在一般范式内工作,是的:

           Bit1 = 0x00000001,
           Bit2 = 0x00000002,
           Bit3 = 0x00000004,
           Bit4 = 0x00000008,
           Bit5 = 0x00000010
        

        【讨论】:

          【解决方案5】:

          取决于需要什么,真的。如果确实需要满足任意数量的位,那么最好有一个循环,从源中逐位提取,组装值,然后在读取正确数量的位后将其写入目标.但是,如果真的只有一组固定的宽度,那么开关和外壳就很好(无论如何在我看来),因为它可能更清楚发生了什么。让代码比它需要的更通用是没有意义的。

          在任何一种情况下,最好将所有这些隐藏在一个函数或其他一些抽象手段后面,以便它可以更容易地重用(“每次”表明这段代码会突然出现在几个地方),而决定的结果只写在一个地方。

          (我要进一步评论的是,如果使用枚举来表示某些固定的位计数集,则每个枚举数应该具有任意值,而不是相应的位计数。这更好地表明该名称不以任何方式表示任意位计数,但只是表示支持的位计数之一的标记。)

          (另外,当读取 16 位字节时,其中一个字节可能来自 input[j+1]。)

          【讨论】:

          • 我认为如果实际位数需要接口(或抽象类)可能具有属性 NumberOfBits (?)
          猜你喜欢
          • 1970-01-01
          • 2015-08-21
          • 2011-07-09
          • 1970-01-01
          • 1970-01-01
          • 2010-10-11
          • 2020-11-17
          • 2020-04-20
          • 2012-05-13
          相关资源
          最近更新 更多