Come si ottiene il valore massimo di un enum?
Come si ottiene il valore massimo di un enum?
Risposte:
Enum.GetValues () sembra restituire i valori in ordine, quindi puoi fare qualcosa del genere:
// given this enum:
public enum Foo
{
Fizz = 3,
Bar = 1,
Bang = 2
}
// this gets Fizz
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
modificare
Per coloro che non sono disposti a leggere i commenti: puoi anche farlo in questo modo:
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... che funzionerà quando alcuni dei tuoi valori enum sono negativi.
Sono d'accordo con la risposta di Matt. Se hai bisogno solo di valori min e max int, puoi farlo come segue.
Massimo:
Enum.GetValues(typeof(Foo)).Cast<int>().Max();
Minimo:
Enum.GetValues(typeof(Foo)).Cast<int>().Min();
Secondo la risposta di Matt Hamilton, ho pensato di creare un metodo di estensione per questo.
Dal momento che ValueType
non è accettato come vincolo di parametro di tipo generico, non ho trovato un modo migliore per limitarmi T
a Enum
quanto segue.
Qualsiasi idea sarebbe davvero apprezzata.
PS. per favore ignora la mia implicazione VB, adoro usare VB in questo modo, questa è la forza di VB ed è per questo che adoro VB.
Howeva, eccolo qui:
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
Questo è leggermente nitido ma il valore massimo effettivo di qualsiasi enum
è Int32.MaxValue
(supponendo che sia enum
derivato da int
). È perfettamente legale assegnare qualsiasi Int32
valore a uno enum
indipendentemente dal fatto che abbia effettivamente dichiarato un membro con quel valore.
Legale:
enum SomeEnum
{
Fizz = 42
}
public static void SomeFunc()
{
SomeEnum e = (SomeEnum)5;
}
Dopo aver provato un'altra volta, ho ottenuto questo metodo di estensione:
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());
}
}
Utilizzare l'ultima funzione non è stato in grado di ottenere il valore massimo. Utilizzare la funzione "max" potrebbe. Piace:
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);
}
}
In accordo con Matthew J Sullivan, per C #:
Enum.GetValues(typeof(MyEnum)).GetUpperBound(0);
Non sono davvero sicuro del motivo per cui qualcuno vorrebbe usare:
Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Last();
... Come parola per parola, semanticamente parlando, non sembra avere molto senso? (sempre bello avere modi diversi, ma non vedo il vantaggio in quest'ultimo.)
Esistono metodi per ottenere informazioni sui tipi enumerati in System.Enum.
Quindi, in un progetto VB.Net in Visual Studio posso digitare "System.Enum". e l'intellisenso fa emergere ogni sorta di bontà.
Un metodo in particolare è System.Enum.GetValues (), che restituisce una matrice dei valori enumerati. Una volta che hai l'array, dovresti essere in grado di fare tutto ciò che è appropriato per le tue circostanze particolari.
Nel mio caso, i miei valori enumerati sono partiti da zero e non sono stati saltati numeri, quindi per ottenere il valore massimo per il mio enum ho solo bisogno di sapere quanti elementi c'erano nell'array.
Frammenti di codice 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()
recupera l' indice più alto possibile nell'array restituito da GetValues()
, non il valore più alto memorizzato all'interno dell'array.
In F #, con una funzione di aiuto per convertire l'enum in una sequenza:
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
Eseguendolo ...
> tipo Foo = | Fizz = 3 | Bang = 2 > val ToSeq: 'A -> seq <' B> quando 'A: enum <' B> > val FooMax: Foo = Fizz
Non when 'A : enum<'B>
è richiesto dal compilatore per la definizione, ma è richiesto per qualsiasi uso di ToSeq, anche per un tipo enum valido.
Non è utilizzabile in tutte le circostanze, ma spesso definisco personalmente il valore massimo:
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));
Ovviamente questo non funzionerà quando si usano valori personalizzati in un enum, ma spesso può essere una soluzione semplice.
Ho usato quanto segue quando avevo bisogno dei valori minimo e massimo del mio enum. Ho appena impostato un min uguale al valore più basso dell'enumerazione e un max uguale al valore più alto dell'enumerazione come valori enum stessi.
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!");
}