简体   繁体   English

如何使用flags属性将枚举格式化为十六进制值?

[英]How to format enum with flags attribute as hex value?

I try to display enum values using the enums ToString method. 我尝试使用枚举ToString方法显示枚举值。 The enum has the Flags attribute. 枚举具有Flags属性。

There are values that don't match any combination of the enum values. 有些值与枚举值的任何组合都不匹配。
In this case, ToString returns the number as decimal, but I want to display it as a hex string. 在这种情况下, ToString将数字作为十进制返回,但我想将其显示为十六进制字符串。

Using ToString("X8") will always return the hex value. 使用ToString("X8")将始终返回十六进制值。

I tried Enum.IsDefined , but it returns only true on non-combined values. 我尝试了Enum.IsDefined ,但它只对非组合值返回true。

Example: 例:

0x00000201 -> "XXt, TSW_AUTO_DETECT"   (known values)
0x00010108 -> "00010108"               (unknown value)

Q: How to "ToString" unknown enum values as hex value? 问:如何将未知枚举值"ToString"作为十六进制值?

You could check if the value has any other bits set than the total bit mask of the flags enumeration. 您可以检查该值是否设置了任何其他位而不是flags枚举的总位掩码。 If so, return the number, otherwise the normal tostring: 如果是这样,返回数字,否则正常的tostring:

public static string GetDescription(EnumName value)
{
    var enumtotal = Enum.GetValues(typeof(EnumName)).Cast<int>().Aggregate((i1, i2) => i1 | i2); //this could be buffered for performance
    if ((enumtotal | (int)value) == enumtotal)
        return value.ToString();
    return ((int)value).ToString("X8");
}

You need to write your own string convertion routine, you can't override ToString() for enums. 您需要编写自己的字符串转换例程,不能为枚举重写ToString()。 In order to format [Flags] look at System.Enum.InternalFlagsFormat: 为了格式化[Flags],请查看System.Enum.InternalFlagsFormat:

private static String InternalFlagsFormat(RuntimeType eT, Object value)
    {
        Contract.Requires(eT != null);
        Contract.Requires(value != null); 
        ulong result = ToUInt64(value);
        HashEntry hashEntry = GetHashEntry(eT); 
        // These values are sorted by value. Don't change this 
        String[] names = hashEntry.names;
        ulong[] values = hashEntry.values; 
        Contract.Assert(names.Length == values.Length);

        int index = values.Length - 1;
        StringBuilder retval = new StringBuilder(); 
        bool firstTime = true;
        ulong saveResult = result; 

        // We will not optimize this code further to keep it maintainable. There are some boundary checks that can be applied
        // to minimize the comparsions required. This code works the same for the best/worst case. In general the number of 
        // items in an enum are sufficiently small and not worth the optimization.
        while (index >= 0)
        {
            if ((index == 0) && (values[index] == 0)) 
                break;

            if ((result & values[index]) == values[index]) 
            {
                result -= values[index]; 
                if (!firstTime)
                    retval.Insert(0, enumSeperator);

                retval.Insert(0, names[index]); 
                firstTime = false;
            } 

            index--;
        } 

        // We were unable to represent this number as a bitwise or of valid flags
        if (result != 0)
            return value.ToString(); 

        // For the case when we have zero 
        if (saveResult==0) 
        {
            if (values.Length > 0 && values[0] == 0) 
                return names[0]; // Zero was one of the enum values.
            else
                return "0";
        } 
        else
        return retval.ToString(); // Return the string representation 
    } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM