webentwicklung-frage-antwort-db.com.de

eine Aufzählung in eine andere Aufzählung umwandeln

Ich habe ein Enum von beispielsweise "Gender" (Male =0 , Female =1) und ich habe ein weiteres Enum von einem Dienst, der ein eigenes Gender-Enum (Male =0 , Female =1, Unknown =2

Meine Frage ist, wie kann ich etwas schnell schreiben und Nizza von ihrem Enum zu meinem konvertieren?

95
kurasa

Die Verwendung einer Erweiterungsmethode funktioniert recht gut, wenn Sie die zwei von Nate vorgeschlagenen Konvertierungsmethoden verwenden:

public static class TheirGenderExtensions
{
    public static MyGender ToMyGender(this TheirGender value)
    {
        // insert switch statement here
    }
}

public static class MyGenderExtensions
{
    public static TheirGender ToTheirGender(this MyGender value)
    {
        // insert switch statement here
    }
}

Natürlich müssen Sie keine separaten Klassen verwenden, wenn Sie dies nicht möchten. Meine Präferenz ist es, Erweiterungsmethoden nach den Klassen/Strukturen/Aufzählungen gruppiert zu lassen, auf die sie angewendet werden.

70
Zooba

Wenn Enum1 value = ... angegeben ist, dann wenn Sie mit Name meinen:

Enum2 value2 = (Enum2) Enum.Parse(typeof(Enum2), value.ToString());

Wenn Sie mit einem numerischen Wert meinen, können Sie in der Regel einfach Folgendes anwenden:

Enum2 value2 = (Enum2)value;

(Mit der Besetzung möchten Sie möglicherweise Enum.IsDefined verwenden, um nach gültigen Werten zu suchen.)

166
Marc Gravell

Setzen Sie einfach eine in int und dann in eine andere Enumeration um (wenn Sie möchten, dass das Mapping basierend auf dem Wert durchgeführt wird):

Gender2 gender2 = (Gender2)((int)gender1);
43
Adrian Zanescu

Um gründlich zu sein, erstelle ich normalerweise ein Paar von Funktionen, eine, die Enum 1 und Enum 2 zurückgibt, und eine andere, die Enum 2 und Enum 1 zurückgibt. Jede besteht aus einer Case-Anweisung, die Eingaben den Ausgaben zuordnet, und der Standardfall löst eine Ausnahme mit einem Nachricht, die sich über einen unerwarteten Wert beschwert.

In diesem speziellen Fall könnten Sie die Tatsache ausnutzen, dass die ganzzahligen Werte von Male und Female die gleichen sind, aber ich würde das vermeiden, da es hackhaft ist und einem Bruch unterliegt, falls sich die Enumeration in der Zukunft ändert.

20
Nate C-K

Sie könnten eine einfache generische Erweiterungsmethode wie diese schreiben

public static T ConvertTo<T>(this object value)            
    where T : struct,IConvertible
{
    var sourceType = value.GetType();
    if (!sourceType.IsEnum)
        throw new ArgumentException("Source type is not enum");
    if (!typeof(T).IsEnum)
        throw new ArgumentException("Destination type is not enum");
    return (T)Enum.Parse(typeof(T), value.ToString());
}
13
Jishnu A P

Wenn wir haben:

enum Gender
{
    M = 0,
    F = 1,
    U = 2
}

und

enum Gender2
{
    Male = 0,
    Female = 1,
    Unknown = 2
}

Wir können das sicher tun

var gender = Gender.M;
var gender2   = (Gender2)(int)gender;

Oder auch

var enumOfGender2Type = (Gender2)0;

Wenn Sie den Fall abdecken möchten, bei dem eine Enumeration auf der rechten Seite des '=' - Zeichens mehr Werte als die Enumeration auf der linken Seite hat, müssen Sie Ihre eigene Methode/ein eigenes Wörterbuch schreiben, um dies zu behandeln, wie von anderen vorgeschlagen.

11
Nedcode

sie könnten eine einfache Funktion wie die folgende schreiben:

public static MyGender ConvertTo(TheirGender theirGender)
{
    switch(theirGender)
    {
        case TheirGender.Male:
            break;//return male
        case TheirGender.Female:
            break;//return female
        case TheirGender.Unknown:
            break;//return whatever
    }
}
7
RCIX

Hier ist eine Erweiterungsmethodenversion, falls jemand interessiert ist

public static TEnum ConvertEnum<TEnum >(this Enum source)
    {
        return (TEnum)Enum.Parse(typeof(TEnum), source.ToString(), true);
    }

// Usage
NewEnumType newEnum = oldEnumVar.ConvertEnum<NewEnumType>();
5
Justin

Ich habe vor einiger Zeit eine Reihe von Erweiterungsmethoden geschrieben, die für verschiedene Arten von Enums funktionieren. Insbesondere funktioniert es für das, was Sie erreichen wollen, und behandelt Enums mit der FlagsAttribute sowie Enums mit verschiedenen zugrunde liegenden Typen.

public static tEnum SetFlags<tEnum>(this Enum e, tEnum flags, bool set, bool typeCheck = true) where tEnum : IComparable
{
    if (typeCheck)
    {
        if (e.GetType() != flags.GetType())
            throw new ArgumentException("Argument is not the same type as this instance.", "flags");
    }

    var flagsUnderlyingType = Enum.GetUnderlyingType(typeof(tEnum));

    var firstNum = Convert.ToUInt32(e);
    var secondNum = Convert.ToUInt32(flags);

    if (set)
        firstNum |= secondNum;

    else
        firstNum &= ~secondNum;

    var newValue = (tEnum)Convert.ChangeType(firstNum, flagsUnderlyingType);

    if (!typeCheck)
    {
        var values = Enum.GetValues(typeof(tEnum));
        var lastValue = (tEnum)values.GetValue(values.Length - 1);

        if (newValue.CompareTo(lastValue) > 0)
            return lastValue;
    }

    return newValue;
}

Von dort aus können Sie weitere spezifischere Erweiterungsmethoden hinzufügen.

public static tEnum AddFlags<tEnum>(this Enum e, tEnum flags) where tEnum : IComparable
{
    SetFlags(e, flags, true);
}

public static tEnum RemoveFlags<tEnum>(this Enum e, tEnum flags) where tEnum : IComparable
{
    SetFlags(e, flags, false);
}

Dieser Typ ändert Enums so, wie Sie es versuchen.

public static tEnum ChangeType<tEnum>(this Enum e) where tEnum : IComparable
{
    return SetFlags(e, default(tEnum), true, false);
}

Seien Sie jedoch gewarnt, dass Sie mit dieser Methode zwischen beliebigen Enum und anderen Enum konvertieren können, auch wenn diese keine Flags haben. Zum Beispiel:

public enum Turtle
{
    None = 0,
    Pink,
    Green,
    Blue,
    Black,
    Yellow
}

[Flags]
public enum WriteAccess : short
{
   None = 0,
   Read = 1,
   Write = 2,
   ReadWrite = 3
}

static void Main(string[] args)
{
    WriteAccess access = WriteAccess.ReadWrite;
    Turtle turtle = access.ChangeType<Turtle>();
}

Die Variable turtle hat den Wert Turtle.Blue.

Es gibt jedoch Sicherheit gegen undefinierte Enum-Werte, die diese Methode verwenden. Zum Beispiel:

static void Main(string[] args)
{
    Turtle turtle = Turtle.Yellow;
    WriteAccess access = turtle.ChangeType<WriteAccess>();
}

In diesem Fall wird access auf WriteAccess.ReadWrite gesetzt, da die WriteAccessEnum einen Maximalwert von 3 hat.

Ein weiterer Nebeneffekt beim Mischen von Enums mit der FlagsAttribute und solchen ohne ist, dass der Konvertierungsprozess nicht zu einer 1-zu-1-Übereinstimmung zwischen ihren Werten führt.

public enum Letters
{
    None = 0,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H
}

[Flags]
public enum Flavors
{
    None = 0,
    Cherry = 1,
    Grape = 2,
    Orange = 4,
    Peach = 8
}

static void Main(string[] args)
{
    Flavors flavors = Flavors.Peach;
    Letters letters = flavors.ChangeType<Letters>();
}

In diesem Fall hat letters einen Wert von Letters.H anstelle von Letters.D, da der Sicherungswert von Flavors.Peach 8 ist. Außerdem würde eine Konvertierung von Flavors.Cherry | Flavors.Grape in LettersLetters.C ergeben, was möglicherweise nicht intuitiv erscheint.

1
Thick_propheT

Sie können ToString () verwenden, um die erste Enumeration in ihren Namen zu konvertieren, und dann Enum.Parse (), um die Zeichenfolge zurück in die andere Enumeration zu konvertieren. Dadurch wird eine Ausnahme ausgelöst, wenn der Wert nicht von der Zielaufzählung unterstützt wird (d. H. Für einen "unbekannten" Wert).

0
Jason Williams

Basierend auf Justin Antwort oben habe ich Folgendes gefunden:

    /// <summary>
    /// Converts Enum Value to different Enum Value (by Value Name) See https://stackoverflow.com/a/31993512/6500501.
    /// </summary>
    /// <typeparam name="TEnum">The type of the enum to convert to.</typeparam>
    /// <param name="source">The source enum to convert from.</param>
    /// <returns></returns>
    /// <exception cref="InvalidOperationException"></exception>
    public static TEnum ConvertTo<TEnum>(this Enum source)
    {
        try
        {
            return (TEnum) Enum.Parse(typeof(TEnum), source.ToString(), ignoreCase: true);
        }
        catch (ArgumentException aex)
        {
            throw new InvalidOperationException
            (
                $"Could not convert {source.GetType().ToString()} [{source.ToString()}] to {typeof(TEnum).ToString()}", aex
            );
        }
    }
0
Sam Jazz

Ich weiß, das ist eine alte Frage und hat viele Antworten. Allerdings finde ich die Verwendung einer switch-Anweisung als akzeptierte Antwort etwas umständlich, daher sind hier meine 2 Cent:

Meine persönliche Lieblingsmethode ist die Verwendung eines Wörterbuchs, wobei der Schlüssel die Quellenzählung ist und der Wert die Zielenzählung ist. In diesem Fall würde der Code folgendermaßen aussehen:

var genderTranslator = new Dictionary<TheirGender, MyGender>();
genderTranslator.Add(TheirGender.Male, MyGender.Male);
genderTranslator.Add(TheirGender.Female, MyGender.Female);
genderTranslator.Add(TheirGender.Unknown, MyGender.Unknown);

// translate their to mine    
var myValue = genderTranslator[TheirValue];

// translate mine to their
var TheirValue = genderTranslator .FirstOrDefault(x => x.Value == myValue).Key;;

Natürlich kann dies in eine statische Klasse eingeschlossen werden und als Erweiterungsmethoden verwendet werden:

public static class EnumTranslator
{

    private static Dictionary<TheirGender, MyGender> GenderTranslator = InitializeGenderTranslator();

    private static Dictionary<TheirGender, MyGender> InitializeGenderTranslator()
    {
        var translator = new Dictionary<TheirGender, MyGender>();
        translator.Add(TheirGender.Male, MyGender.Male);
        translator.Add(TheirGender.Female, MyGender.Female);
        translator.Add(TheirGender.Unknown, MyGender.Unknown);
        return translator;
    }

    public static MyGender Translate(this TheirGender theirValue)
    {
        return GenderTranslator[theirValue];
    }

    public static TheirGender Translate(this MyGender myValue)
    {
        return GenderTranslator.FirstOrDefault(x => x.Value == myValue).Key;
    }

}
0
Zohar Peled
public static TEnum ConvertByName<TEnum>(this Enum source, bool ignoreCase = false) where TEnum : struct
{
    // if limited by lack of generic enum constraint
    if (!typeof(TEnum).IsEnum)
    {
        throw new InvalidOperationException("enumeration type required.");
    }

    TEnum result;
    if (!Enum.TryParse(source.ToString(), ignoreCase, out result))
    {
        throw new Exception("conversion failure.");
    }

    return result;
}
0
epistemophilic