Làm thế nào để bạn có được giá trị tối đa của một enum?
Làm thế nào để bạn có được giá trị tối đa của một enum?
Câu trả lời:
Enum.GetValues () dường như trả về các giá trị theo thứ tự, vì vậy bạn có thể làm một cái gì đó như thế này:
// given this enum:
public enum Foo
{
Fizz = 3,
Bar = 1,
Bang = 2
}
// this gets Fizz
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
Biên tập
Đối với những người không sẵn sàng đọc qua các bình luận: Bạn cũng có thể làm theo cách này:
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... sẽ hoạt động khi một số giá trị enum của bạn âm.
Tôi đồng ý với câu trả lời của Matt. Nếu bạn chỉ cần các giá trị tối thiểu và tối đa, thì bạn có thể làm như sau.
Tối đa:
Enum.GetValues(typeof(Foo)).Cast<int>().Max();
Tối thiểu:
Enum.GetValues(typeof(Foo)).Cast<int>().Min();
Theo câu trả lời của Matt Hamilton, tôi đã nghĩ đến việc tạo ra một phương thức mở rộng cho nó.
Kể từ khi ValueType
không được chấp nhận như là một hạn chế tham số kiểu chung chung, tôi không tìm thấy một cách tốt hơn để hạn chế T
đến Enum
nhưng sau.
Bất kỳ ý tưởng sẽ được thực sự đánh giá cao.
Tái bút xin vui lòng bỏ qua nhân chứng VB của tôi, tôi thích sử dụng VB theo cách này, đó là thế mạnh của VB và đó là lý do tại sao tôi yêu VB.
Howeva, đây là:
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
Điều này hơi nitpicky nhưng giá trị tối đa thực tế của bất kỳ enum
là Int32.MaxValue
(giả sử nó enum
có nguồn gốc từ int
). Hoàn toàn hợp pháp khi đưa bất kỳ Int32
giá trị nào cho bất kỳ giá trị nào, bất enum
kể nó có thực sự tuyên bố thành viên có giá trị đó hay không.
Hợp pháp:
enum SomeEnum
{
Fizz = 42
}
public static void SomeFunc()
{
SomeEnum e = (SomeEnum)5;
}
Sau khi thử một lần khác, tôi đã nhận được phương thức mở rộng này:
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());
}
}
Sử dụng chức năng Cuối cùng không thể có được giá trị tối đa. Sử dụng chức năng "tối đa" có thể. Giống:
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);
}
}
Đồng ý với Matthew J Sullivan, cho C #:
Enum.GetValues(typeof(MyEnum)).GetUpperBound(0);
Tôi thực sự không chắc chắn tại sao mọi người muốn sử dụng:
Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Last();
... Là từng từ, nói theo ngữ nghĩa, nó dường như không có ý nghĩa nhiều như vậy? (luôn luôn tốt để có những cách khác nhau, nhưng tôi không thấy lợi ích sau này.)
Có các phương pháp để nhận thông tin về các kiểu liệt kê trong System.Enum.
Vì vậy, trong một dự án VB.Net trong Visual Studio, tôi có thể gõ "System.Enum." và intellisense mang đến tất cả các loại lòng tốt.
Một phương thức cụ thể là System.Enum.GetValues (), trả về một mảng các giá trị được liệt kê. Khi bạn đã có được mảng, bạn sẽ có thể làm bất cứ điều gì phù hợp với hoàn cảnh cụ thể của bạn.
Trong trường hợp của tôi, các giá trị được liệt kê của tôi bắt đầu từ 0 và không bỏ qua các số nào, vì vậy để có được giá trị tối đa cho enum của tôi, tôi chỉ cần biết có bao nhiêu phần tử trong mảng.
Đoạn mã 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()
lấy chỉ số cao nhất có thể trong mảng được trả về GetValues()
, không phải giá trị cao nhất được lưu trữ bên trong mảng đó.
Trong F #, với chức năng trợ giúp để chuyển enum thành chuỗi:
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
Chạy nó ...
> gõ Foo = | Fizz = 3 | Bang = 2 > val ToSeq: 'A -> seq <' B> khi 'A: enum <' B> > val FooMax: Foo = Fizz
Các when 'A : enum<'B>
không theo yêu cầu của trình biên dịch cho các định nghĩa, nhưng là cần thiết cho bất kỳ sử dụng ToSeq, thậm chí theo một kiểu enum hợp lệ.
Nó không thể sử dụng được trong mọi trường hợp, nhưng tôi thường tự xác định giá trị tối đa:
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));
Tất nhiên điều này sẽ không hoạt động khi bạn sử dụng các giá trị tùy chỉnh trong enum, nhưng thường thì nó có thể là một giải pháp dễ dàng.
Tôi đã sử dụng như sau khi tôi cần các giá trị tối thiểu và tối đa của enum của tôi. Tôi chỉ đặt một phút bằng giá trị liệt kê thấp nhất và tối đa bằng giá trị cao nhất trong bảng liệt kê như chính giá trị 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!");
}