C# 将枚举转换为另一种类型的枚举

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1818131/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 21:05:29  来源:igfitidea点击:

convert an enum to another type of enum

c#enums

提问by kurasa

I have an enum of for example 'Gender' (Male =0 , Female =1) and I have another enum from a service which has its own Gender enum (Male =0 , Female =1, Unknown =2)

我有一个例如 ' Gender' ( Male =0 , Female =1) 的枚举,我有另一个来自具有自己的 Gender 枚举 ( Male =0 , Female =1, Unknown =2)的服务的枚举

My question is how can I write something quick and nice to convert from their enum to mine?

我的问题是我怎样才能写出一些快速而漂亮的东西来从他们的枚举转换为我的枚举?

采纳答案by Zooba

Using an extension method works quite neatly, when using the two conversion methods suggested by Nate:

当使用 Nate 建议的两种转换方法时,使用扩展方法非常有效:

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
    }
}

Obviously there's no need to use separate classes if you don't want to. My preference is to keep extension methods grouped by the classes/structures/enumerations they apply to.

显然,如果您不想,则无需使用单独的类。我的偏好是将扩展方法按它们适用的类/结构/枚举分组。

回答by Nate C-K

To be thorough I normally create a pair of functions, one that takes Enum 1 and returns Enum 2 and another that takes Enum 2 and returns Enum 1. Each consists of a case statement mapping inputs to outputs and the default case throws an exception with a message complaining about an unexpected value.

为了彻底,我通常创建一对函数,一个接受 Enum 1 并返回 Enum 2,另一个接受 Enum 2 并返回 Enum 1。每个都包含一个 case 语句,将输入映射到输出,并且默认 case 抛出一个异常抱怨意外值的消息。

In this particular case you could take advantage of the fact that the integer values of Male and Female are the same, but I'd avoid that as it's hackish and subject to breakage if either enum changes in the future.

在这种特殊情况下,您可以利用男性和女性的整数值相同的事实,但我会避免这种情况,因为如果将来任何一个枚举发生变化,它都是黑客行为并且可能会损坏。

回答by Marc Gravell

Given Enum1 value = ..., then if you mean by name:

Given Enum1 value = ...,那么如果您指的是名称:

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

If you mean by numeric value, you can usually just cast:

如果你的意思是数值,你通常可以只转换:

Enum2 value2 = (Enum2)value;

(with the cast, you might want to use Enum.IsDefinedto check for valid values, though)

(不过,使用演员表,您可能想用它Enum.IsDefined来检查有效值)

回答by Jason Williams

You can use ToString() to convert the first enum to its name, and then Enum.Parse() to convert the string back to the other Enum. This will throw an exception if the value is not supported by the destination enum (i.e. for an "Unknown" value)

您可以使用 ToString() 将第一个枚举转换为其名称,然后使用 Enum.Parse() 将字符串转换回另一个枚举。如果目标枚举不支持该值(即“未知”值),这将引发异常

回答by RCIX

you could write a simple function like the following:

你可以写一个简单的函数,如下所示:

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
    }
}

回答by Adrian Zanescu

Just cast one to int and then cast it to the other enum (considering that you want the mapping done based on value):

只需将一个转换为 int,然后将其转换为另一个枚举(考虑到您希望根据值完成映射):

Gender2 gender2 = (Gender2)((int)gender1);

回答by Jishnu A P

You could write a simple generic extension method like this

您可以像这样编写一个简单的通用扩展方法

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());
}

回答by Thick_propheT

I wrote a set extension methods a while back that work for several different kinds of Enums. One in particular works for what you are trying to accomplish and handles Enums with the FlagsAttributeas well as Enums with different underlying types.

不久前我写了一套扩展方法,适用于几种不同类型的Enums。一种特别适用于您要完成的工作,并使用EnumsFlagsAttribute以及Enum具有不同底层类型的 s来处理。

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;
}

From there you can add other more specific extension methods.

从那里您可以添加其他更具体的扩展方法。

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);
}

This one will change types of Enums like you are trying to do.

这将Enum像您尝试做的那样改变s 的类型。

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

Be warned, though, that you CAN convert between any Enumand any other Enumusing this method, even those that do not have flags. For example:

但是请注意,您可以使用此方法在任何Enum和任何其他之间进行转换Enum,即使是那些没有标志的。例如:

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>();
}

The variable turtlewill have a value of Turtle.Blue.

该变量turtle的值为Turtle.Blue

However, there is safety from undefined Enumvalues using this method. For instance:

但是,Enum使用此方法可以避免未定义的值。例如:

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

In this case, accesswill be set to WriteAccess.ReadWrite, since the WriteAccessEnumhas a maximum value of 3.

在这种情况下,access将设置为WriteAccess.ReadWrite,因为 的WriteAccessEnum最大值为 3。

Another side effect of mixing Enums with the FlagsAttributeand those without it is that the conversion process will not result in a 1 to 1 match between their values.

Enums 与 sFlagsAttribute和不带s混合的另一个副作用是转换过程不会导致它们的值之间 1 比 1 匹配。

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 this case, letterswill have a value of Letters.Hinstead of Letters.D, since the backing value of Flavors.Peachis 8. Also, a conversion from Flavors.Cherry | Flavors.Grapeto Letterswould yield Letters.C, which can seem unintuitive.

在这种情况下,letters将有一个值Letters.H而不是Letters.D,因为 的支持值Flavors.Peach是 8。此外,从Flavors.Cherry | Flavors.Grape到的转换Letters会产生Letters.C,这似乎不直观。

回答by Justin

Here's an extension method version if anyone is interested

如果有人感兴趣,这是一个扩展方法版本

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

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

回答by Nedcode

If we have:

如果我们有:

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

and

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

We can safely do

我们可以安全地做

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

Or even

甚至

var enumOfGender2Type = (Gender2)0;

If you want to cover the case where an enum on the right side of the '=' sign has more values than the enum on the left side - you will have to write your own method/dictionary to cover that as others suggested.

如果您想涵盖“=”符号右侧的枚举比左侧的枚举具有更多值的情况 - 您将必须编写自己的方法/字典来涵盖其他人的建议。