簡體   English   中英

從逗號分隔的列表或整數中解析枚舉標志

[英]Parsing enum flags from comma-separated list or integer

我有一個包含幾個標志的XML,其中一些是無符號的32位整數,另一些是無符號的64位整數。 其中一些是用逗號分隔的列表編寫的,另一些是十六進制的。

看這個例子:

<Color>Blue,Red</Color>
<Color>0xC</Color>

因為我不想編寫解析每個枚舉的方法,所以我決定使用泛型方法。 但Visual Studio不會讓我構建解決方案。 這是我的方法:

public static T ParseFlags<T>(string value) where T : struct
{
    T result = (T)((object)0);
    string[] array;
    // Remove white spaces and delimit string if it is comma-separated
    if (ParseDelimitedString(value, ',', out array))
    {
        for (int i = 0; i < array.Length; i++)
        {
            T flag = (T)((object)0);
            // Check if value is member of enumeration
            if (Enum.TryParse<T>(array[i], out flag))
            {
                result |= (T)((object)flag);
            }
        }
    }
    else
    {
        switch (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T))))
        {
            // Remove hex characters and parse node's inner text
            case TypeCode.UInt32:
                result = (T)((object)ParseUint(value));
                break;
            case TypeCode.UInt64:
                result = (T)((object)ParseUlong(value));
                break;
        }
    }
    return result;
}

我得到的錯誤信息是:

錯誤1運算符'| ='不能應用於'T'和'T'類型的操作數

有沒有辦法做到這一點?

你正在做很多可以為你做的工作。 例如,如果使用FlagsAttribute聲明enum ,則Enum.Parse將為您解析逗號分隔值。

public static T ParseFlags<T>(string value) where T : struct
{
    T result;
    ulong temp;
    if (Enum.TryParse(value, out result))
    {
        return result;
    }

    string hexNum = value.StartsWith("0x") ? value.Substring(2) : value;
    if (ulong.TryParse(hexNum, NumberStyles.HexNumber, null, out temp))
    {
        return (T)Enum.ToObject(typeof(T), temp);
    }

    throw new ArgumentException("value could not be parsed");
}

我使用具有shortintulong支持值的各種Flags枚舉類型對此進行了測試。

如果你知道你正在解析什么類型的枚舉:

    [Fact]
    public void when_parsing_options_then_can_combine_flags()
    {
        var values = "Singleline | Compiled";

        var options = values.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
            .Select(value => (RegexOptions)Enum.Parse(typeof(RegexOptions), value))
            .Aggregate(RegexOptions.None, (current, value) => current |= value);

        Assert.Equal(RegexOptions.Singleline | RegexOptions.Compiled, options);
    }

嘗試這個:

public static T ParseFlags<T>(string value) where T : struct
{
    long result = 0L;
    string[] array;
    // Remove white spaces and delimit string if it is comma-separated
    if (ParseDelimitedString(value, ',', out array))
    {
        for (int i = 0; i < array.Length; i++)
        {
            T flag = default(T);
            // Check if value is member of enumeration
            if (Enum.TryParse<T>(array[i], out flag))
            {
                result |= (long)flag;
            }
        }
    }
    else
    {
        switch (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T))))
        {
            // Remove hex characters and parse node's inner text
            case TypeCode.UInt32:
                result = ParseUint(value);
                break;
            case TypeCode.UInt64:
                result = ParseUlong(value);
                break;
        }
    }
    return (T)((object)result);
}

希望能幫助到你。

“| =”該片段中的用法讓我覺得你的意思是將Enum用作bitset而不僅僅是任何舊的Enum。 如果這是真的,你應該做一個小改動 - 將本地“result”聲明為int並適當調整轉換,你的return語句應該是“return(T)(object)result;”。 與“|”有關的那一行 看起來像:“result | =(int)(object)flag;”。 也許,有一個更好的答案,但是,請注意, 枚舉是整數,並且您的bitset的場景已經足夠覆蓋此解決方案,除非有我錯過的情況或您沒有陳述。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM