Перечисление и константы - PullRequest
1 голос
/ 06 февраля 2009

Есть ли лучший способ, чем объявить перечисление как

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
}

Спасибо.

Ответы [ 5 ]

1 голос
/ 06 февраля 2009

Вместо этого вы можете рассмотреть использование классов, возможно, с помощью метода фабрики, чтобы вернуть правильный конкретный тип для размера, например,

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 в остальной части кода. И, конечно, у вас может быть несколько методов для каждого типа того, что вам нужно сделать.

Трудно сказать, подходит ли это для вашего приложения, так как не так много контекста, но это другой подход, который можно использовать в ситуациях такого типа.

1 голос
/ 06 февраля 2009

Вы можете сделать что-то вроде этого:

    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();

Таким образом, вы можете удалить переключатель.

0 голосов
/ 06 февраля 2009

Зависит от того, что нужно, правда. Если на самом деле необходимо обслуживать произвольное количество битов, то было бы лучше иметь цикл, который вылавливает биты один за другим из источника, собирает значение, а затем записывает его в место назначения после считывания нужного количества бит. , Но, если на самом деле есть только фиксированный набор ширины, то переключатель и корпус в порядке (на мой взгляд, в любом случае), так как, вероятно, яснее, что происходит. Нет смысла делать код более общим, чем нужно.

В любом случае, вероятно, было бы лучше спрятать все это за функцией или каким-либо другим средством абстракции, чтобы его можно было легко использовать повторно («каждый раз» предполагает, что этот фрагмент кода возникает в нескольких местах), а результат решения записан только в одном месте.

(Еще один комментарий, который я хотел бы сделать, заключается в том, что при использовании перечисления для представления некоторого фиксированного набора счетчиков битов каждый перечислитель должен иметь произвольное значение, а не соответствующий счетчик битов. Это лучше указывает на то, что имя не имеет никакого значения означает произвольный счетчик битов, но скорее просто токен, указывающий один из поддерживаемых счетчиков битов.)

(Также при чтении 16 битов один из байтов, вероятно, должен поступить из input[j+1].)

0 голосов
/ 06 февраля 2009

Работая в рамках этой общей парадигмы, да:

   Bit1 = 0x00000001,
   Bit2 = 0x00000002,
   Bit3 = 0x00000004,
   Bit4 = 0x00000008,
   Bit5 = 0x00000010
0 голосов
/ 06 февраля 2009

Я думаю, вам, возможно, понадобится уточнить ваш вопрос.

Однако вы можете получить базовое значение вашего перечисления, преобразовав его в байт (тип перечислений по умолчанию).

(byte)DepthNumberSize.Bit8

вернет 8. Было бы лучше, так как вы на самом деле использовали бы пользовательские значения, которые вы дали своему перечислению (по умолчанию они равны 0, 1, 2 и т. Д.). Это может даже позволить вам избавиться от всего оператора switch, позволяя написать общий фрагмент кода, который использует базовое значение переменной enum 'size' для получения желаемого результата.

...