Di ottenere il massimo valore di un enum
Domanda
Come si fa a ottenere il massimo valore di un enum?
Soluzione
Enum.GetValues() sembra riportare i valori in ordine, in modo che si può fare qualcosa di simile a questo:
// given this enum:
public enum Foo
{
Fizz = 3,
Bar = 1,
Bang = 2
}
// this gets Fizz
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
Modifica
Per chi non è disposto a leggere i commenti:Si può anche fare in questo modo:
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
...che quando alcuni dei tuoi valori enum sono negativi.
Altri suggerimenti
Sono d'accordo con la risposta di Matt. Se hai bisogno solo di valori min e max int, puoi farlo come segue.
massima:
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 esso.
Poiché ValueType
non è accettato come vincolo di parametro di tipo generico, non ho trovato un modo migliore per limitare T
a Enum
ma 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:
C #:
static void Main(string[] args)
{
MyEnum x = GetMaxValue<MyEnum>();
}
public static TEnum GetMaxValue<TEnum>()
where TEnum : IComparable, IConvertible, IFormattable
//In C#>=7.3 substitute with 'where TEnum : Enum', and remove the following check:
{
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
}
VB:
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 un enum derivato da int). È perfettamente legale trasmettere qualsiasi valore Int32 a qualsiasi 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 il & Quot; max & Quot; funzione potrebbe. Come:
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.)
Ci sono metodi per ottenere informazioni circa i tipi enumerati sotto il Sistema.Enum.
Così, in un VB.Net progetto in Visual Studio posso tipo di Sistema".Enum." e l'intellisense porta a ogni sorta di bontà.
Un metodo, in particolare, è di Sistema.Enum.GetValues(), che restituisce un array di valori enumerati.Una volta ottenuta la matrice, si dovrebbe essere in grado di fare tutto ciò che è appropriato per le vostre particolari circostanze.
Nel mio caso, i miei valori enumerati iniziato a zero e saltato numeri, in modo da ottenere il massimo valore per il mio enum ho solo bisogno di sapere quanti elementi dell'array.
VB.Net frammenti di codice:
'''''''
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")
'''''''
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 ...
> type Foo = | Fizz = 3 | Bang = 2 > val ToSeq : 'A -> seq<'B> when 'A : enum<'B> > val FooMax : Foo = Fizz
Il when 'A : enum<'B>
non è 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.