Jak uzyskać maksymalną wartość wyliczenia?
Jak uzyskać maksymalną wartość wyliczenia?
Odpowiedzi:
Enum.GetValues () wydaje się zwracać wartości w kolejności, więc możesz zrobić coś takiego:
// given this enum:
public enum Foo
{
Fizz = 3,
Bar = 1,
Bang = 2
}
// this gets Fizz
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
Edytować
Dla tych, którzy nie chcą czytać komentarzy: Możesz to również zrobić w ten sposób:
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... co zadziała, gdy niektóre wartości wyliczenia są ujemne.
Zgadzam się z odpowiedzią Matta. Jeśli potrzebujesz tylko minimalnych i maksymalnych wartości int, możesz to zrobić w następujący sposób.
Maksymalny:
Enum.GetValues(typeof(Foo)).Cast<int>().Max();
Minimum:
Enum.GetValues(typeof(Foo)).Cast<int>().Min();
Zgodnie z odpowiedzią Matta Hamiltona, pomyślałem o stworzeniu dla niego metody rozszerzenia.
Ponieważ ValueTypenie są akceptowane jako parametr typu rodzajowego przymusu, nie mogę znaleźć lepszy sposób, aby ograniczyć Tdo Enumale następujący.
Wszelkie pomysły byłyby naprawdę mile widziane.
PS. proszę zignoruj moją niejawność VB, uwielbiam używać VB w ten sposób, to jest siła VB i dlatego kocham VB.
Howeva, oto jest:
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
Jest to trochę dziwaczne, ale rzeczywista maksymalna wartość dowolnego enumto Int32.MaxValue(zakładając, że enumpochodzi z int). Całkowicie legalne jest rzutowanie dowolnej Int32wartości na dowolną, enumniezależnie od tego, czy faktycznie zadeklarowała ona członka o tej wartości.
Prawny:
enum SomeEnum
{
Fizz = 42
}
public static void SomeFunc()
{
SomeEnum e = (SomeEnum)5;
}
Po ponownym wypróbowaniu otrzymałem tę metodę rozszerzenia:
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());
}
}
Użyj funkcji Last nie może uzyskać maksymalnej wartości. Użyj funkcji „max”. Lubić:
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);
}
}
W porozumieniu z Matthew J Sullivanem, dla C #:
Enum.GetValues(typeof(MyEnum)).GetUpperBound(0);
Naprawdę nie jestem pewien, dlaczego ktoś miałby chcieć użyć:
Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Last();
... Jako słowo w słowo, mówiąc semantycznie, nie wydaje się to mieć aż tyle sensu? (zawsze dobrze jest mieć różne sposoby, ale nie widzę korzyści w tym drugim).
Istnieją metody uzyskiwania informacji o typach wyliczeniowych w System.Enum.
Tak więc w projekcie VB.Net w Visual Studio mogę wpisać „System.Enum”. a inteligencja przynosi wszelkiego rodzaju dobro.
W szczególności jedną z metod jest System.Enum.GetValues (), która zwraca tablicę wyliczonych wartości. Kiedy już masz tablicę, powinieneś być w stanie zrobić wszystko, co jest odpowiednie dla twoich szczególnych okoliczności.
W moim przypadku moje wyliczone wartości zaczynały się od zera i nie pomijały żadnych liczb, więc aby uzyskać maksymalną wartość dla mojego wyliczenia, muszę tylko wiedzieć, ile elementów było w tablicy.
Fragmenty kodu 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()pobiera najwyższy możliwy indeks w tablicy zwrócony przez GetValues(), a nie najwyższą wartość przechowywaną w tej tablicy.
W F #, z funkcją pomocniczą, aby przekonwertować wyliczenie na sekwencję: In F #, with a helper function to convert the enum to a sequence:
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
Uruchamiam to ...
> wpisz Foo = | Fizz = 3 | Bang = 2 > val ToSeq: 'A -> seq <' B> when 'A: enum <' B> > val FooMax: Foo = Fizz
when 'A : enum<'B>Nie jest wymagane przez kompilator dla definicji, ale wymagana jest ich wykorzystanie ToSeq, nawet przy pomocy ważnego typu wyliczeniowego.
Nie nadaje się do użytku w każdych okolicznościach, ale często sam definiuję maksymalną wartość:
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));
Oczywiście to nie zadziała, gdy używasz wartości niestandardowych w wyliczeniu, ale często może to być łatwe rozwiązanie.
Użyłem następujących, gdy potrzebowałem wartości minimalnej i maksymalnej mojego wyliczenia. Po prostu ustawiłem min równe najniższej wartości wyliczenia i maksimum równe najwyższej wartości w wyliczeniu jako same wartości wyliczeniowe.
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!");
}