简体   繁体   中英

“&” in an enum?

I want to consume some files and I need to know where to put each of the data. One column is called "Category".

I can have many categories and I want to build an enum to support them.

public enum GasKeyWords
       {
           Gas,
           Fuel,
           Gas&Fuel
       }

 public enum EducationKeyWord
 {
    Education,
    Books&Supplies,
    StudentLoan
    Tuition
 }

I am thinking of something like this

 foreach(var r in records)
 {
      Categories.GasKeyWords GasKeyWords;

      bool valid = Enum.TryParse<Categories.GasKeyWords>(r, out GasKeyWords);

       if (valid)
        {
                // add to group
        }
 }

and keep using TryParse till I find a group it can parse too. I am not sure if this is the best way to do it(I am always open to better ideas).

However the problem I facing right now is that I can't use "&" in enum names. I don't have control of these category names so I can't change it.

Why not use the Description tag to work around this problem. Granted it is not exactly what it was designed for but if you take issue with that then you can always invent your own attribute class.

Here is a quick a dirty method I wrote for getting the description attribute of a object

    public static string GetDescription(this object enumeration)
    {
        //Again, not going to do your condition/error checking here.
        //Normally I would have made this extension method for the Enum type
        but you won't know the type at compile time when building the list of descriptions but ..
        // you will know its an object so that is how I cheated around it.

        var desc = enumeration.GetType().GetMember(enumeration.ToString())[0]
            .GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[];

        if (desc != null && desc.Length > 0)
        {
            return desc[0].Description;
        }

        return enumeration.ToString();
    }

Here is a quick a dirty utility method to get a list of all descriptors of an object as a list

public static IList<string> GetDescriptions<E>(E type)
{
    //I'm not going to do your error checking for you. 
    //Figure out what you want to do in the event that this isn't an enumeration. 
    //Or design it to support different cases. =P

    var list = new List<string>(); 
    foreach(var name in Enum.GetNames(typeof(E)))
    {
        var enumObj = (E) Enum.Parse(typeof(E), name);
        list.Add(enumObj.GetDescription());
    }
    return list;
}

Now for utilizing these to the effect you need

   public enum GasKeyWords
   {
       [Description("Gas")] 
       Gas,
       [Description("Fuel")]
       Fuel,
       [Description("Gas&Fuel")]
       GasFuel
   }

   ...


   var gasKeywords = Util.GetDescriptions<GasKeywords>();
   foreach(var r in records)
   {
        var found = gasKeywords.Contains(r);
        if (found)
        {

        }
   }

I'm not a generics master. If anyone has some ideas on how to get around the typing issues of the GetDescriptions() method that would be welcome. Unfortunately, I couldn't put a type constraint that expected Enum which makes this less than friendly to code around.

I've done something like this in my own project... edited for brevity...

USAGE: GetType(Operators).GetTitle(tName))

IMPLEMENTATION:

 <AttributeUsage(AttributeTargets.Field, AllowMultiple:=False, Inherited:=False)>
    Public Class EnumItemAttribute
        Inherits Attribute

        Public Property Title As String = String.Empty

        Public Property Description As String = String.Empty

    End Class

<Extension()>
    Public Function GetTitle(ByVal tEnum As Type, ByVal tItemName As String) As String

        Dim tFieldInfo As FieldInfo = Nothing

        tFieldInfo = tEnum.GetField(tItemName)
        For Each tAttribute As EnumItemAttribute In tFieldInfo.GetCustomAttributes(GetType(EnumItemAttribute), False)
            Return tAttribute.Title
        Next

        Return String.Empty

    End Function

AC# identifier must start with an underscore, a character in the Unicode class Lu, Ll, Lt, Lm, Lo, or Nl, or an escape for one of those. All other characters must be from Unicode class Lu, Ll, Lt, Lm, Lo, Nl, Mn, Mc, Nd, Pc or Cf, or an escape for one of those.

An identifier can begin with @ but this is not part of the identifier but used to allow the same word as a keyword to be an identifier. Hence myVar and @myVar are the same identifier, while @if is a valid identifier while we couldn't use if because it would conflict with the keyword.

(§ 2.4.2 of the C# spec).

& is of class Po, and hence not covered by the rules.

For CLS-compliant identifiers, ECMA-335 requires identifiers to follow http://www.unicode.org/reports/tr15/tr15-18.html Annex 7, canonicalised to NFC, and without having names distinct by case alone, which is stricter still.

In short, you can't.

More to the point, why would you want to? How could you tell Gas&Fuel an identifier from Gas&Fuel an expression that has Gas and Fuel as operands to the & operator?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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