คุณจะรับค่าสูงสุดของ enum ได้อย่างไร
คุณจะรับค่าสูงสุดของ enum ได้อย่างไร
คำตอบ:
Enum.GetValues () ดูเหมือนว่าจะส่งกลับค่าตามลำดับดังนั้นคุณสามารถทำสิ่งนี้:
// given this enum:
public enum Foo
{
Fizz = 3,
Bar = 1,
Bang = 2
}
// this gets Fizz
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
แก้ไข
สำหรับผู้ที่ไม่ต้องการอ่านความคิดเห็น: คุณสามารถทำเช่นนี้ได้:
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... ซึ่งจะทำงานเมื่อค่า enum ของคุณบางค่าเป็นลบ
ฉันเห็นด้วยกับคำตอบของ Matt หากคุณต้องการเพียงค่า min และ max int คุณสามารถทำได้ดังนี้
ขีดสุด:
Enum.GetValues(typeof(Foo)).Cast<int>().Max();
จำนวนขั้นต่ำ:
Enum.GetValues(typeof(Foo)).Cast<int>().Min();
ตามคำตอบของ Matt Hamilton ฉันคิดว่าการสร้างวิธีการขยายสำหรับมัน
เนื่องจากValueType
ไม่ได้รับการยอมรับว่าเป็นข้อ จำกัด ประเภททั่วไปพารามิเตอร์ฉันไม่พบวิธีที่ดีกว่าที่จะ จำกัดT
การEnum
แต่ต่อไปนี้
ความคิดใด ๆ ที่จะได้รับการชื่นชมจริงๆ
PS โปรดเพิกเฉยต่อ VB implicitness ของฉันฉันชอบใช้ VB ด้วยวิธีนี้นั่นคือจุดแข็งของ VB และนั่นคือเหตุผลที่ฉันรัก VB
Howeva นี่คือ:
static void Main(string[] args)
{
MyEnum x = GetMaxValue<MyEnum>(); //In newer versions of C# (7.3+)
MyEnum y = GetMaxValueOld<MyEnum>();
}
public static TEnum GetMaxValue<TEnum>()
where TEnum : Enum
{
return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Max();
}
//When C# version is smaller than 7.3, use this:
public static TEnum GetMaxValueOld<TEnum>()
where TEnum : IComparable, IConvertible, IFormattable
{
Type type = typeof(TEnum);
if (!type.IsSubclassOf(typeof(Enum)))
throw new
InvalidCastException
("Cannot cast '" + type.FullName + "' to System.Enum.");
return (TEnum)Enum.ToObject(type, Enum.GetValues(type).Cast<int>().Last());
}
enum MyEnum
{
ValueOne,
ValueTwo
}
Public Function GetMaxValue _
(Of TEnum As {IComparable, IConvertible, IFormattable})() As TEnum
Dim type = GetType(TEnum)
If Not type.IsSubclassOf(GetType([Enum])) Then _
Throw New InvalidCastException _
("Cannot cast '" & type.FullName & "' to System.Enum.")
Return [Enum].ToObject(type, [Enum].GetValues(type) _
.Cast(Of Integer).Last)
End Function
นี่เป็น nitpicky เล็กน้อย แต่มูลค่าสูงสุดที่แท้จริงของใด ๆenum
คือInt32.MaxValue
(สมมติว่ามันenum
มาจากint
) เป็นเรื่องถูกกฎหมายอย่างสมบูรณ์ที่จะนำInt32
มูลค่าใด ๆไปใช้enum
โดยไม่คำนึงว่าจะประกาศสมาชิกด้วยมูลค่านั้นหรือไม่
กฎหมาย:
enum SomeEnum
{
Fizz = 42
}
public static void SomeFunc()
{
SomeEnum e = (SomeEnum)5;
}
หลังจากลองอีกครั้งฉันได้รับวิธีการขยายนี้:
public static class EnumExtension
{
public static int Max(this Enum enumType)
{
return Enum.GetValues(enumType.GetType()).Cast<int>().Max();
}
}
class Program
{
enum enum1 { one, two, second, third };
enum enum2 { s1 = 10, s2 = 8, s3, s4 };
enum enum3 { f1 = -1, f2 = 3, f3 = -3, f4 };
static void Main(string[] args)
{
Console.WriteLine(enum1.one.Max());
}
}
ใช้ฟังก์ชั่นสุดท้ายไม่สามารถรับค่าสูงสุด ใช้ฟังก์ชั่น "max" ได้ ชอบ:
class Program
{
enum enum1 { one, two, second, third };
enum enum2 { s1 = 10, s2 = 8, s3, s4 };
enum enum3 { f1 = -1, f2 = 3, f3 = -3, f4 };
static void Main(string[] args)
{
TestMaxEnumValue(typeof(enum1));
TestMaxEnumValue(typeof(enum2));
TestMaxEnumValue(typeof(enum3));
}
static void TestMaxEnumValue(Type enumType)
{
Enum.GetValues(enumType).Cast<Int32>().ToList().ForEach(item =>
Console.WriteLine(item.ToString()));
int maxValue = Enum.GetValues(enumType).Cast<int>().Max();
Console.WriteLine("The max value of {0} is {1}", enumType.Name, maxValue);
}
}
ตามข้อตกลงกับ Matthew J Sullivan สำหรับ C #:
Enum.GetValues(typeof(MyEnum)).GetUpperBound(0);
ฉันไม่แน่ใจจริงๆว่าทำไมทุกคนต้องการใช้:
Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Last();
... ในฐานะที่เป็นคำต่อคำพูดเชิงความหมายดูเหมือนจะไม่สมเหตุสมผลใช่ไหม? (ดีเสมอที่จะมีวิธีต่าง ๆ แต่ฉันไม่เห็นประโยชน์ในภายหลัง)
มีวิธีการรับข้อมูลเกี่ยวกับประเภทที่ระบุภายใต้ System.Enum
ดังนั้นในโครงการ VB.Net ใน Visual Studio ฉันสามารถพิมพ์ "System.Enum" และ Intellisense นำมาซึ่งความดีทุกประเภท
วิธีการหนึ่งโดยเฉพาะอย่างยิ่งคือ System.Enum.GetValues () ซึ่งส่งกลับอาร์เรย์ของค่าที่แจกแจง เมื่อคุณได้รับชุดคุณควรจะสามารถทำสิ่งที่เหมาะสมกับสถานการณ์ของคุณ
ในกรณีของฉันค่าที่แจกแจงของฉันเริ่มต้นที่ศูนย์และไม่ต้องข้ามตัวเลขดังนั้นเพื่อให้ได้ค่าสูงสุดสำหรับ enum ของฉันฉันแค่ต้องรู้ว่ามีองค์ประกอบอยู่ในอาร์เรย์เท่าใด
ตัวอย่างโค้ด VB.Net:
'''''''
Enum MattType
zerothValue = 0
firstValue = 1
secondValue = 2
thirdValue = 3
End Enum
'''''''
Dim iMax As Integer
iMax = System.Enum.GetValues(GetType(MattType)).GetUpperBound(0)
MessageBox.Show(iMax.ToString, "Max MattType Enum Value")
'''''''
GetUpperBound()
ดึงดัชนีที่เป็นไปได้สูงสุดในอาร์เรย์ที่ส่งคืนโดยGetValues()
ไม่ใช่ค่าสูงสุดที่เก็บไว้ในอาร์เรย์นั้น
ใน F # ด้วยฟังก์ชันตัวช่วยในการแปลง enum เป็นลำดับ:
type Foo =
| Fizz = 3
| Bang = 2
// Helper function to convert enum to a sequence. This is also useful for iterating.
// stackoverflow.com/questions/972307/can-you-loop-through-all-enum-values-c
let ToSeq (a : 'A when 'A : enum<'B>) =
Enum.GetValues(typeof<'A>).Cast<'B>()
// Get the max of Foo
let FooMax = ToSeq (Foo()) |> Seq.max
เรียกใช้ ...
> พิมพ์ Foo = | Fizz = 3 | บาง = 2 > val ToSeq: 'A -> seq <' B> เมื่อ 'A: enum <' B> > val FooMax: Foo = Fizz
when 'A : enum<'B>
ไม่จำเป็นต้องใช้คอมไพเลอร์สำหรับความหมาย แต่เป็นสิ่งจำเป็นสำหรับการใช้งานของ ToSeq ใด ๆ แม้โดยแบ่งตามชนิด enum ที่ถูกต้อง
มันไม่สามารถใช้งานได้ในทุกสถานการณ์ แต่ฉันมักจะกำหนดค่าสูงสุดด้วยตนเอง:
enum Values {
one,
two,
tree,
End,
}
for (Values i = 0; i < Values.End; i++) {
Console.WriteLine(i);
}
var random = new Random();
Console.WriteLine(random.Next((int)Values.End));
แน่นอนว่าสิ่งนี้จะไม่ทำงานเมื่อคุณใช้ค่าที่กำหนดเองใน enum แต่บ่อยครั้งอาจเป็นวิธีแก้ปัญหาที่ง่าย
ฉันใช้สิ่งต่อไปนี้เมื่อฉันต้องการค่า min และค่าสูงสุดของ enum ของฉัน ฉันเพิ่งตั้งค่านาทีเท่ากับค่าต่ำสุดของการแจงนับและสูงสุดเท่ากับค่าสูงสุดในการแจงนับเป็นค่า enum ตัวเอง
public enum ChannelMessageTypes : byte
{
Min = 0x80, // Or could be: Min = NoteOff
NoteOff = 0x80,
NoteOn = 0x90,
PolyKeyPressure = 0xA0,
ControlChange = 0xB0,
ProgramChange = 0xC0,
ChannelAfterTouch = 0xD0,
PitchBend = 0xE0,
Max = 0xE0 // Or could be: Max = PitchBend
}
// I use it like this to check if a ... is a channel message.
if(... >= ChannelMessageTypes.Min || ... <= ChannelMessages.Max)
{
Console.WriteLine("Channel message received!");
}