4

我有一个包含多个标志的 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”类型的操作数

有没有办法做到这一点?

4

4 回答 4

8

你正在做很多可以为你完成的工作。例如,如果您使用thenenum声明,则会为您解析逗号分隔的值。FlagsAttributeEnum.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");
}

short我使用具有、intulong支持值的各种 Flags 枚举类型对此进行了测试。

于 2013-01-06T08:01:57.283 回答
1

如果您知道要解析的枚举类型:

    [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);
    }
于 2015-05-09T18:27:00.637 回答
0

试试这个:

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

希望能帮助到你。

于 2013-01-06T08:01:34.727 回答
0

该片段中的“|=”用法使我认为您打算将枚举用作位集,而不仅仅是任何旧的枚举。如果这是真的,你应该做一个小的改变 - 将本地“结果”声明为 int 并适当地调整强制转换,那么你的返回语句应该是“返回 (T)(object)result;”。带有“|”的那一行 看起来像:“结果 |= (int)(object)flag;”。也许,有一个更好的答案,但请注意,枚举是整数,并且您的 bitset 方案已被此解决方案充分覆盖,除非有我错过的情况或您没有说明的情况。

于 2013-01-06T08:11:28.903 回答