views:

168

answers:

5

Is there better way than declare enumeration as

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

and every time when operations with related data chunk performed switch statements are used, like:

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
}

?

Thanks.

+1  A: 

You could do something like this:

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

Then you can call it like this:

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

This way you can remove the switch.

Nathan W
A: 

I think you may need to clarify your question some.

However, you can get the underlying value of your enum by casting it to a byte (the default type of enums).

(byte)DepthNumberSize.Bit8

will return 8. It would be better since you'd actually be utilizing the custom values you gave your enum (They default to 0, 1, 2, etc.). It may even allow you to get rid of the whole switch statement, allowing you to write a generic chunk of code that uses the underlying value of the enum variable 'size' to produce the desired result.

colithium
+1  A: 

You could consider the use of classes instead, possibly with a factory method to return the correct concrete type for the size, e.g.

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

You've then just got a single switch statement, and then all the logic can be contained in the size-specific classes rather than littered through switch statements in the rest of the code. And of course, you can have multiple methods for each type of thing you need to do.

It's hard to say whether this is appropriate for your application as there isn't a lot of context, but it's another approach that can be used in this type of situation.

Greg Beech
A: 

Working within that general paradigm, yes:

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

Depends what is needed, really. If it's actually necessary to cater for arbitrary numbers of bits then it would be better to have a loop that fishes bits one by one out of the source, assembles the value, then writes it into the destination once the right number of bits has been read. But, if there really are only a fixed set of widths then the switch and case is fine (to my eyes anyway), as it is probably clearer what is going on. There's no point making the code more generic than it needs to be.

In either case, it would probably be better to have all of this hidden behind a function, or some other means of abstraction, so that it can be reused more easily ("every time" suggests that this bit of code crops up in several places), and the result of the decision written only in one place.

(A further comment I would make is that if using an enum to represent some fixed set of bit counts each enumerant should have an arbitrary value, rather than the corresponding bit count. This better indicates that the name does not in any way signify an arbitrary bit count, but is rather simply a token indicating one of the supported bit counts.)

(Also when reading 16 bits one of the bytes should probably come from input[j+1].)

brone
I think in case when amount of actual bits need interface (or abstract class) may have property NumberOfBits (?)
LicenseQ