4

いくつかのフラグを含む XML があります。そのうちのいくつかは符号なし 32 ビット整数で、その他は符号なし 64 ビット整数です。それらの一部はコンマ区切りのリストで記述され、その他は 16 進形式で記述されています。

次の例を参照してください。

<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

あなたはあなたのためにできる多くの仕事をしています。たとえば、 yourが the 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");
}

shortint、およびulongバッキング値を持つさまざまな Flags 列挙型でこれをテストしました。

于 2013-01-06T08:01:57.283 に答える
0

そのスニペットで「| =」を使用すると、Enumを古いEnumだけでなくビットセットとして使用するつもりだったと思います。これが当てはまる場合は、小さな変更を加える必要があります。ローカルの「結果」を int として宣言し、キャストを適切に調整すると、return ステートメントは「return (T)(object)result;」になります。「|」で問題の行 「result |= (int)(object)flag;」のようになります。おそらく、より良い答えがあるかもしれませんが、列挙型は整数であり、ビットセットのシナリオは、私が見逃した、またはあなたが述べていない状況がない限り、このソリューションで十分にカバーされていることに注意してください。

于 2013-01-06T08:11:28.903 に答える
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 に答える