开发者

When you use flag(Enum) you have a limit of 64. What are the alternative when you reach the limit?

With enum under .net the biggest number you can use is ULong.

This mean a maximum of 64 flags.

What would be the alternative when you need more than 64 flags?

Edit

Sorry, I forgot to add this, alternative that would still work with bitwise operations at least these one; and and or.

using Josh Einstein suggestion, I came up with this, does it make sense?

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

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

开发者_JAVA技巧        flagBit[flagPos] = false;
        flagPos += 1;
        flagBit[flagPos] = true;
        flagN = new BitArray(flagBit);
    }
}


That many flags seems excessive and would suggest a redesign is needed. However, you could consider using two sets of flags. The first to designate the "flag group" and the second to designate the flags within that group. You'd have to have a class that then managed your "grouped enum" so that you could test if a flag was set or not in a simple way.

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


You could then switch to using a BitArray. You would lose all the "features" of an enum such as the default string formatting and parsing ability. A BitArray would be fundamentally similar to having a bunch of boolean fields except that the storage is much more efficient.

Indeed as Jeff says in the comments with that many independent bit states it seems like an Enum is the wrong solution anyway. A BitArray may be much more suitable for your particular scenario.


When you need more than 64 flags, you can use the 128-flags version.

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);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜