C#函数接受枚举项并返回枚举值(不是索引)

时间:2023-01-26 13:09:53

say I have the following declarations:

说我有以下声明:

public enum Complexity { Low = 0, Normal = 1, Medium = 2,  High = 3 }
public enum Priority { Normal = 1, Medium = 2,  High = 3, Urgent = 4 }

and I want to code it so that I could get the enum value (not the index, like I earlier mentioned):

我想编码它,以便我可以得到枚举值(不是索引,就像我之前提到的):

//should store the value of the Complexity enum member Normal, which is 1
int complexityValueToStore = EnumHelper.GetEnumMemberValue(Complexity.Normal); 
//should store the value 4
int priorityValueToStore = EnumHelper.GetEnumMemberValue(Priority.Urgent); 

How should this reusable function look like?

这个可重用的函数应该怎么样?

tia! -ren

6 个解决方案

#1


Revised answer (after question clarification)

修改后的答案(问题澄清后)

No, there's nothing cleaner than a cast. It's more informative than a method call, cheaper, shorter etc. It's about as low impact as you could possibly hope for.

不,没有什么比演员更干净了。它比方法调用,更便宜,更短等更具信息性。它的影响力与您可能希望的一样低。

Note that if you wanted to write a generic method to do the conversion, you'd have to specify what to convert it to as well: the enum could be based on byte or long for example. By putting in the cast, you explicitly say what you want to convert it to, and it just does it.

请注意,如果您想编写一个通用方法来进行转换,则必须指定将其转换为的内容:例如,enum可以基于byte或long。通过投入演员,你明确地说出你要将它转换成什么,它就是这样做的。

Original answer

What do you mean by "index" exactly? Do you mean the numeric value? Just cast to int. If you mean "position within enum" you'd have to make sure the values are in numeric order (as that's what Enum.GetValues gives - not the declaration order), and then do:

你对“索引”的意思是什么?你的意思是数值吗?刚转到int。如果你的意思是“在枚举中的位置”,你必须确保这些值是按数字顺序排列的(因为这是Enum.GetValues给出的 - 而不是声明顺序),然​​后执行:

public static int GetEnumMemberIndex<T>(T element)
    where T : struct
{
    T[] values = (T[]) Enum.GetValues(typeof(T));
    return Array.IndexOf(values, element);
}

#2


You can find the integer value of an enum by casting:

您可以通过强制转换找到枚举的整数值:

int complexityValueToStore = (int)Complexity.Normal;

#3


The most generic way I know of is to read the value__ field using reflection. This approach makes no assumptions about the enum's underlying type so it will work on enums that aren't based on Int32.

我所知道的最通用的方法是使用反射读取value__字段。这种方法不会对枚举的基础类型做出任何假设,因此它将适用于不基于Int32的枚举。

public static object GetValue(Enum e)
{
    return e.GetType().GetField("value__").GetValue(e);
}

Debug.Assert(Equals(GetValue(DayOfWeek.Wednesday), 3));                //Int32
Debug.Assert(Equals(GetValue(AceFlags.InheritOnly), (byte) 8));        //Byte
Debug.Assert(Equals(GetValue(IOControlCode.ReceiveAll), 2550136833L)); //Int64

Note: I have only tested this with the Microsoft C# compiler. It's a shame there doesn't appear to be a built in way of doing this.

注意:我只使用Microsoft C#编译器对此进行了测试。遗憾的是,这似乎并没有内置的方式。

#4


I realize this isn't what you asked, but it's something you might appreciate.

我意识到这不是你问的问题,但是你可能会欣赏它。

I discovered that you can find the integer value of an enum without a cast, if you know what the enum's minimum value is:

我发现如果你知道枚举的最小值是什么,你可以找到没有强制转换的枚举的整数值:

public enum Complexity { Low = 0, Normal = 1, Medium = 2,  High = 3 }

int valueOfHigh = Complexity.High - Complexity.Low;

This wouldn't work with Priority, unless you added some minimal value of 0, or added 1 back:

这不适用于Priority,除非您添加了一些最小值0或添加了1:

public enum Priority { Normal = 1, Medium = 2,  High = 3, Urgent = 4 }

int valueOfUrgent = Priority.Urgent - Priority.Normal + 1;

I find this technique much more aesthetically appealing than casting to int.

我觉得这种技术比铸造到int更具美学吸引力。

I'm not sure off the top of my head what happens if you have an enum based on byte or long -- I suspect that you'd get byte or long difference values.

我不确定如果你有一个基于字节或长的枚举会发生什么 - 我怀疑你会得到字节或长差值。

#5


If you want the value, you can just cast the enum to int. That would set complexityValueToStore == 1 and priorityValueToStore == 4.

如果你想要这个值,你可以将枚举转换为int。这将设置complexityValueToStore == 1和priorityValueToStore == 4。

If you want to get the index (ie: Priority.Urgent == 3), you could use Enum.GetValues, then just find the index of your current enum in that list. However, the ordering of the enum in the list returned may not be the same as in your code.

如果你想获得索引(即:Priority.Urgent == 3),你可以使用Enum.GetValues,然后只需在该列表中找到当前枚举的索引。但是,返回的列表中枚举的顺序可能与您的代码中的顺序不同。

However, the second option kind of defeats the purpose of Enum in the first place - you're trying to have discrete values instead of lists and indices. I'd rethink your needs if that is what you want.

然而,第二种选择首先打败了Enum的目的 - 你试图拥有离散值而不是列表和索引。如果那就是你想要的,我会重新考虑你的需求。

#6


This is the most simple way to solve your problem:

这是解决问题的最简单方法:

public static void GetEnumMemberValue<T>(T enumItem) where T : struct 
{
    return (int) Enum.Parse(typeof(T), enumItem.ToString());
}

It works for me.

这个对我有用。

#1


Revised answer (after question clarification)

修改后的答案(问题澄清后)

No, there's nothing cleaner than a cast. It's more informative than a method call, cheaper, shorter etc. It's about as low impact as you could possibly hope for.

不,没有什么比演员更干净了。它比方法调用,更便宜,更短等更具信息性。它的影响力与您可能希望的一样低。

Note that if you wanted to write a generic method to do the conversion, you'd have to specify what to convert it to as well: the enum could be based on byte or long for example. By putting in the cast, you explicitly say what you want to convert it to, and it just does it.

请注意,如果您想编写一个通用方法来进行转换,则必须指定将其转换为的内容:例如,enum可以基于byte或long。通过投入演员,你明确地说出你要将它转换成什么,它就是这样做的。

Original answer

What do you mean by "index" exactly? Do you mean the numeric value? Just cast to int. If you mean "position within enum" you'd have to make sure the values are in numeric order (as that's what Enum.GetValues gives - not the declaration order), and then do:

你对“索引”的意思是什么?你的意思是数值吗?刚转到int。如果你的意思是“在枚举中的位置”,你必须确保这些值是按数字顺序排列的(因为这是Enum.GetValues给出的 - 而不是声明顺序),然​​后执行:

public static int GetEnumMemberIndex<T>(T element)
    where T : struct
{
    T[] values = (T[]) Enum.GetValues(typeof(T));
    return Array.IndexOf(values, element);
}

#2


You can find the integer value of an enum by casting:

您可以通过强制转换找到枚举的整数值:

int complexityValueToStore = (int)Complexity.Normal;

#3


The most generic way I know of is to read the value__ field using reflection. This approach makes no assumptions about the enum's underlying type so it will work on enums that aren't based on Int32.

我所知道的最通用的方法是使用反射读取value__字段。这种方法不会对枚举的基础类型做出任何假设,因此它将适用于不基于Int32的枚举。

public static object GetValue(Enum e)
{
    return e.GetType().GetField("value__").GetValue(e);
}

Debug.Assert(Equals(GetValue(DayOfWeek.Wednesday), 3));                //Int32
Debug.Assert(Equals(GetValue(AceFlags.InheritOnly), (byte) 8));        //Byte
Debug.Assert(Equals(GetValue(IOControlCode.ReceiveAll), 2550136833L)); //Int64

Note: I have only tested this with the Microsoft C# compiler. It's a shame there doesn't appear to be a built in way of doing this.

注意:我只使用Microsoft C#编译器对此进行了测试。遗憾的是,这似乎并没有内置的方式。

#4


I realize this isn't what you asked, but it's something you might appreciate.

我意识到这不是你问的问题,但是你可能会欣赏它。

I discovered that you can find the integer value of an enum without a cast, if you know what the enum's minimum value is:

我发现如果你知道枚举的最小值是什么,你可以找到没有强制转换的枚举的整数值:

public enum Complexity { Low = 0, Normal = 1, Medium = 2,  High = 3 }

int valueOfHigh = Complexity.High - Complexity.Low;

This wouldn't work with Priority, unless you added some minimal value of 0, or added 1 back:

这不适用于Priority,除非您添加了一些最小值0或添加了1:

public enum Priority { Normal = 1, Medium = 2,  High = 3, Urgent = 4 }

int valueOfUrgent = Priority.Urgent - Priority.Normal + 1;

I find this technique much more aesthetically appealing than casting to int.

我觉得这种技术比铸造到int更具美学吸引力。

I'm not sure off the top of my head what happens if you have an enum based on byte or long -- I suspect that you'd get byte or long difference values.

我不确定如果你有一个基于字节或长的枚举会发生什么 - 我怀疑你会得到字节或长差值。

#5


If you want the value, you can just cast the enum to int. That would set complexityValueToStore == 1 and priorityValueToStore == 4.

如果你想要这个值,你可以将枚举转换为int。这将设置complexityValueToStore == 1和priorityValueToStore == 4。

If you want to get the index (ie: Priority.Urgent == 3), you could use Enum.GetValues, then just find the index of your current enum in that list. However, the ordering of the enum in the list returned may not be the same as in your code.

如果你想获得索引(即:Priority.Urgent == 3),你可以使用Enum.GetValues,然后只需在该列表中找到当前枚举的索引。但是,返回的列表中枚举的顺序可能与您的代码中的顺序不同。

However, the second option kind of defeats the purpose of Enum in the first place - you're trying to have discrete values instead of lists and indices. I'd rethink your needs if that is what you want.

然而,第二种选择首先打败了Enum的目的 - 你试图拥有离散值而不是列表和索引。如果那就是你想要的,我会重新考虑你的需求。

#6


This is the most simple way to solve your problem:

这是解决问题的最简单方法:

public static void GetEnumMemberValue<T>(T enumItem) where T : struct 
{
    return (int) Enum.Parse(typeof(T), enumItem.ToString());
}

It works for me.

这个对我有用。