70 Stimmen

Convert.ChangeType und Konvertierung in Enums?

Ich habe eine Int16 Wert aus der Datenbank und müssen diesen in einen Aufzählungstyp konvertieren. Dies geschieht leider in einer Schicht des Codes, die nur sehr wenig über die Objekte weiß, außer dem, was sie durch Reflexion sammeln kann.

Als solches endet es mit dem Aufruf Convert.ChangeType die mit einer ungültigen Cast-Ausnahme fehlschlägt.

Ich habe eine, wie ich finde, stinkende Abhilfe gefunden, etwa so:

String name = Enum.GetName(destinationType, value);
Object enumValue = Enum.Parse(destinationType, name, false);

Gibt es einen besseren Weg, so dass ich mich nicht durch diese String-Operation bewegen muss?

Hier ist ein kurzes, aber vollständiges Programm, das für Experimente verwendet werden kann:

using System;

public class MyClass
{
    public enum DummyEnum
    {
        Value0,
        Value1
    }

    public static void Main()
    {
        Int16 value = 1;
        Type destinationType = typeof(DummyEnum);

        String name = Enum.GetName(destinationType, value);
        Object enumValue = Enum.Parse(destinationType, name, false);

        Console.WriteLine("" + value + " = " + enumValue);
    }
}

95voto

Peter Punkte 34999

Enum.ToObject(.... ist das, wonach Sie suchen!

C#

StringComparison enumValue = (StringComparison)Enum.ToObject(typeof(StringComparison), 5);

VB.NET

Dim enumValue As StringComparison = CType([Enum].ToObject(GetType(StringComparison), 5), StringComparison)

Wenn Sie eine Menge von Enum konvertieren versuchen, mit der folgenden Klasse wird es sparen Sie viel Code.

public class Enum<EnumType> where EnumType : struct, IConvertible
{

    /// <summary>
    /// Retrieves an array of the values of the constants in a specified enumeration.
    /// </summary>
    /// <returns></returns>
    /// <remarks></remarks>
    public static EnumType[] GetValues()
    {
        return (EnumType[])Enum.GetValues(typeof(EnumType));
    }

    /// <summary>
    /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    /// <remarks></remarks>
    public static EnumType Parse(string name)
    {
        return (EnumType)Enum.Parse(typeof(EnumType), name);
    }

    /// <summary>
    /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.
    /// </summary>
    /// <param name="name"></param>
    /// <param name="ignoreCase"></param>
    /// <returns></returns>
    /// <remarks></remarks>
    public static EnumType Parse(string name, bool ignoreCase)
    {
        return (EnumType)Enum.Parse(typeof(EnumType), name, ignoreCase);
    }

    /// <summary>
    /// Converts the specified object with an integer value to an enumeration member.
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    /// <remarks></remarks>
    public static EnumType ToObject(object value)
    {
        return (EnumType)Enum.ToObject(typeof(EnumType), value);
    }
}

Anstatt nun zu schreiben (StringComparison)Enum.ToObject(typeof(StringComparison), 5); können Sie einfach schreiben Enum<StringComparison>.ToObject(5); .

0voto

Artur A Punkte 5541

Basierend auf der Antwort von @Peter ist hier die Methode für Nullable<int> à Enum Umwandlung:

public static class EnumUtils
{
        public static bool TryParse<TEnum>(int? value, out TEnum result)
            where TEnum: struct, IConvertible
        {
            if(!value.HasValue || !Enum.IsDefined(typeof(TEnum), value)){
                result = default(TEnum);
                return false;
            }
            result = (TEnum)Enum.ToObject(typeof(TEnum), value);
            return true;
        }
}

Verwendung von EnumUtils.TryParse<YourEnumType>(someNumber, out result) wird für viele Szenarien nützlich. Zum Beispiel hat der WebApi Controller in Asp.NET keinen Standardschutz gegen ungültige Enum-Parameter. Asp.NET verwendet einfach default(YourEnumType) Wert, auch wenn einige Pässe null , -1000 , 500000 , "garbage string" oder ignoriert den Parameter völlig. Außerdem, ModelState ist in all diesen Fällen gültig, so dass eine der Lösungen in der Verwendung von int? Typ mit benutzerdefinierter Prüfung

public class MyApiController: Controller
{
    [HttpGet]
    public IActionResult Get(int? myEnumParam){    
        MyEnumType myEnumParamParsed;
        if(!EnumUtils.TryParse<MyEnumType>(myEnumParam, out myEnumParamParsed)){
            return BadRequest($"Error: parameter '{nameof(myEnumParam)}' is not specified or incorrect");
        }      

        return this.Get(washingServiceTypeParsed);            
    }
    private IActionResult Get(MyEnumType myEnumParam){ 
       // here we can guarantee that myEnumParam is valid
    }

0voto

Cassova Punkte 533

Wenn Sie ein Enum in einer DataTable speichern, aber nicht wissen, welche Spalte ein Enum und welche ein String/Int ist, können Sie auf diese Weise auf den Wert zugreifen:

foreach (DataRow dataRow in myDataTable.Rows)
{
    Trace.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
    foreach (DataColumn dataCol in myDataTable.Columns)
    {
        object v = dataRow[dataCol];
        Type t = dataCol.DataType;
        bool e = false;
        if (t.IsEnum) e = true;

        Trace.WriteLine((dataCol.ColumnName + ":").PadRight(30) +
            (e ? Enum.ToObject(t, v) : v));
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X