Когда вы используете флаг (Enum), у вас есть предел 64. Какая альтернатива, когда вы достигаете предела?

С перечислением под .net самым большим числом, которое вы можете использовать, является ULong.
Это означает максимум 64 флага.

Какая альтернатива, если вам нужно больше 64 флагов?

Edit

Извините, я забыл добавить эту альтернативу, которая по-прежнему будет работать с побитовыми операциями, по крайней мере, такими; и и или.

используя предложение Джош Эйнштейна, я придумал это, имеет ли смысл?

class bitArrayFlag
{
    private const int flagSize = 255; //allow X numbers of flags

    public BitArray flag1;
    public BitArray flag2;
    public BitArray flagN;

    public bitArrayFlag()
    {
        int flagPos = 0;
        bool[] flagBit = new bool[flagSize];

        flagBit[flagPos] = true;
        flag1 = new BitArray(flagBit);

        flagBit[flagPos] = false;
        flagPos += 1;
        flagBit[flagPos] = true;
        flag2 = new BitArray(flagBit);

        //...
        //...
        //...

        flagBit[flagPos] = false;
        flagPos += 1;
        flagBit[flagPos] = true;
        flagN = new BitArray(flagBit);
    }
}

Ответ 1

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

Действительно, как говорит Джефф в комментариях к этому множеству независимых состояний бит, похоже, что Enum - это неправильное решение. BitArray может быть гораздо более подходящим для вашего конкретного сценария.

Ответ 2

То, что многие флаги кажутся чрезмерными и предполагает, что необходима редизайн. Однако вы можете использовать два набора флагов. Первый обозначает "группа флагов", а второй - флаги внутри этой группы. Вы должны иметь класс, который затем управлял вашим "сгруппированным перечислением", чтобы вы могли проверить, был ли установлен флаг или нет.

struct BigFlags<TGroupEnum, TFlagEnum>
{
    private Dictionary<TGroupEnum, TFlagEnum> flags;

    public BigFlags(IDictionary<TGroupEnum, TFlagEnum> flags)
    {
        this.flags = new Dictionary<TGroupEnum, TFlagEnum>(flags);
    }

    public BigFlags(TGroupEnum group, TFlagEnum flags)
    {
        this.flags = new Dictionary<TGroupEnum, TFlagEnum>() { { group, flags } };
    }

    public bool Contains(BigFlags<TGroupEnum, TFlagEnum> flags)
    {
        // TODO: Compare dictionaries and see if the passed flags are a subset of these flags.
    }

    // TODO: Equality to check exact match
    // TODO: Logical operators and operators for setting/removing flags.
}

Ответ 3

Если вам нужно больше 64 флагов, вы можете использовать версию с 128 флагами.

public class BigFlags<TEnumHi, TEnumLo>
{
    private long _hi;
    private long _lo;

    public bool HasFlags(TEnumHi value)
    {
        var hiValue = (long)(object)value;

        return (_hi & hiValue) == hiValue;
    }

    public bool HasFlags(TEnumLo value)
    {
        var loValue = (long)(object)value;

        return (_lo & loValue) == loValue;
    }

    public bool HasFlags(TEnumHi hiPart, TEnumLo loPart)
    {
        return HasFlags(hiPart) && HasFlags(loPart);
    }

    public void SetFlags(TEnumHi value)
    {
        var hiValue = (long)(object)value;

        _hi = _hi | hiValue;
    }

    public void SetFlags(TEnumLo value)
    {
        var loValue = (long)(object)value;

        _lo = _lo | loValue;
    }

    public override string ToString()
    {
        var hiEnum = ((TEnumHi)(object)_hi).ToString();
        var loEnum = ((TEnumLo)(object)_lo).ToString();

        if (hiEnum.Length == 0)
        {
            return loEnum;
        }

        if (loEnum.Length == 0)
        {
            return hiEnum;
        }

        return string.Concat(hiEnum, " , ", loEnum);
    }
}