valor truncar redondear numero menos mas hacia ejemplos como arriba abajo c# .net

truncar - redondear numero hacia arriba c#



Cómo obtener el siguiente valor de enumeración(o anterior) en C# (20)

¿ Realmente necesitas generalizar este problema? ¿Puedes hacer esto en su lugar?

public void SomeMethod(MyEnum myEnum) { MyEnum? nextMyEnum = myEnum.Next(); if (nextMyEnum.HasValue) { ... } } public static MyEnum? Next(this MyEnum myEnum) { switch (myEnum) { case MyEnum.A: return MyEnum.B; case MyEnum.B: return MyEnum.C; case MyEnum.C: return MyEnum.D; default: return null; } }

Tengo una enumeración que se define así:

public enum eRat { A = 0, B=3, C=5, D=8 };

Entonces, dado el valor de eRat.B , quiero obtener el siguiente, que es eRat.C

La solución que veo es (sin verificación de rango)

Array a = Enum.GetValues(typeof(eRat)); int i=0 ; for (i = 0; i < a.GetLength(); i++) { if (a.GetValue(i) == eRat.B) break; } return (eRat)a.GetValue(i+1):

Ahora que es demasiada complejidad, por algo tan simple. ¿Conoces alguna mejor solución? Algo como eRat.B+1 o Enum.Next(Erat.B) ?

Gracias


¿Estás encerrado en el uso de una enumeración por algo sobre lo que no tienes control?

Si no lo eres, te sugiero usar una alternativa, probablemente Dictionary<string, int> rat;

Si crea un Dictionary y lo rellena con sus datos, enumerarlo es algo más simple. Además, se trata de un mapeo de intenciones más claro: estás asignando números a las cadenas con esta enumeración y estás tratando de aprovechar esa asignación.

Si debe usar la enumeración, sugeriría algo más:

var rats = new List<eRat>() {eRat.A, eRat.B, eRat.C, eRat.D};

Mientras agregue los valores en orden y los mantenga sincronizados, simplificará en gran medida el acto de recuperar el próximo eRat.


A juzgar por su descripción, realmente no quiere una enumeración. Estás estirando enum más allá de sus capacidades. ¿Por qué no crear una clase personalizada que expone los valores que necesita como propiedades, mientras los mantiene en OrderedDictionary? Entonces obtener una siguiente / anterior sería trivial. --actualizar

Si desea enumerar de manera diferente en la colección basada en el contexto, haga esa parte explícita de su diseño. Encapsule los elementos dentro de una clase, y tenga pocos métodos cada uno que vuelva IEnumerable donde, T es su tipo deseado.

Por ejemplo

IEnumerable<Foo> GetFoosByBar() IEnumerable<Foo> GetFoosByBaz()

etc ...


De los comentarios tuve muchas preguntas como: "¿Por qué querrías usar enum de esta manera?" Como muchos de ustedes preguntaron, déjenme darle mi caso de uso y ver si están de acuerdo:

Tengo una matriz fija de elementos int[n] . Dependiendo de la situación que deseo enumerar a través de este arreglo de manera diferente. Así que definí:

int[] Arr= {1,2,34,5,6,78,9,90,30}; enum eRat1 { A = 0, B=3, C=5, D=8 }; enum eRat2 { A, AA,AAA,B,BB,C,C,CC,D }; void walk(Type enumType) { foreach (Type t in Enum.GetValues(enumType)) { write(t.ToString() + " = " + Arr[(int)t)]; } }

y call walk(typeof(eRAt1)) o walk(typeof(eRAt2))

entonces obtengo la salida requerida

1) caminar (typeof (eRAt1))

A = 1 B = 5 C = 78 D = 30

2) walk(typeof(eRAt2))

A = 1 AA = 2 AAA = 34 B = 5 BB = 6 C = 78 CC = 90 D = 30

Esto es muy simplificado. Pero espero, esto explica. Hay algunas otras ventajas a esto, como tener enum.toString (). Así que, básicamente, uso enumeraciones como indexadores.

Entonces, usando la solución, puedo hacer algo como esto ahora.

En la secuencia eRat1, el siguiente valor para B es C, pero en eRat2 es BB. De modo que, dependiendo de la secuencia en la que esté interesado, puedo hacer e.next y, dependiendo de enumType, obtendré C o BB. ¿Cómo se podría lograr eso con los diccionarios?

Creo que es un uso bastante elegante de enums.


El problema al que se enfrenta es porque intentas hacer que una enumeración haga algo que no debería hacer. Se supone que son de tipo seguro. Se permite asignar valores enteros a una enumeración para que pueda combinarlos, pero si desea que representen valores integrales, use clases o estructuras. Aquí hay una posible alternativa:

public static class eRat { public static readonly eRatValue A; public static readonly eRatValue B; public static readonly eRatValue C; public static readonly eRatValue D; static eRat() { D = new eRatValue(8, null); C = new eRatValue(5, D); B = new eRatValue(3, C); A = new eRatValue(0, B); } #region Nested type: ERatValue public class eRatValue { private readonly eRatValue next; private readonly int value; public eRatValue(int value, eRatValue next) { this.value = value; this.next = next; } public int Value { get { return value; } } public eRatValue Next { get { return next; } } public static implicit operator int(eRatValue eRatValue) { return eRatValue.Value; } } #endregion }

Esto te permite hacer esto:

int something = eRat.A + eRat.B;

y esto

eRat.eRatValue current = eRat.A; while (current != null) { Console.WriteLine(current.Value); current = current.Next; }

En realidad, solo debería utilizar enumeraciones cuando pueda beneficiarse de su tipo de seguridad. Si confía en ellos para representar un tipo, cambie a constantes o a clases.

EDITAR

Sugeriría que eche un vistazo a la página de MSDN sobre Enumeration Design . La primera mejor práctica es:

Use una enumeración para escribir con fuerza los parámetros, las propiedades y los valores de retorno que representan conjuntos de valores.

Intento no discutir un dogma, por lo que no lo haré, pero este es el problema al que te enfrentarás. Microsoft no quiere que hagas lo que intentas hacer. Le piden explícitamente que no haga lo que está tratando de hacer. Te dificultan hacer lo que tratas de hacer. Para lograr lo que estás tratando de hacer, tienes que construir un código de utilidad para forzar que parezca funcionar.

Ha llamado su solución elegante más de una vez, y podría ser si las enumeraciones se diseñaron de una manera diferente, pero como las enumeraciones son lo que son, su solución no es elegante. Creo que la música de cámara es elegante, pero si los músicos no tuvieran los instrumentos adecuados y tuvieran que tocar Vivaldi con hojas de sierra y jarras, ya no sería elegante, sin importar cuán capaces fueran como músicos o cuán buena sea la música. estaba en papel.


Espero que esta parte de mi código te ayude a:

public enum EGroupedBy { Type, InterfaceAndType, Alpha, _max } private void _btnViewUnit_Click(object sender, EventArgs e) { int i = (int)GroupedBy; i = (i + 1) % (int)EGroupedBy._max; GroupedBy = (EGroupedBy) i; RefreshUnit(); }


Estoy usando esto aquí:

public MyEnum getNext() { return this.ordinal() < MyEnum.values().length - 1 ? MyEnum.values()[this.ordinal() + 1] : MyEnum.values()[0]; }


Estoy usando esto, perfecto para mi.

//=================================================================================== // NEXT VALUE IN ENUM // ex: E_CamModes eNew = kGlobalsVars.eGetNextValue< E_CamModes >( geCmMode ); public static T eGetNextValue< T >( T eIn ){ T[] aiAllValues = ( T[] ) Enum.GetValues( typeof( T )); int iVal = System.Array.IndexOf( aiAllValues, eIn ); return aiAllValues[ ( iVal + 1 ) % aiAllValues.Length ]; }


Existe una solución muy simple (si puede cambiar sus valores enteros) diseñada específicamente para trabajar con números. El hecho de que tu número sea una enum no es un problema. Sigue siendo el integer (o cualquier tipo de número subyacente que asigne). Enum simplemente agrega la complejidad de un requisito de conversión.

Suponga que su enum se define así:

public enum ItemStatus { New = 0, Draft = 1, Received = 2, Review = 4, Rejected = 8, Approved = 16 } ItemStatus myStatus = ItemStatus.Draft;

Use operaciones bit a bit en el Enum . Por ejemplo:

myStatus = (ItemStatus)(((int)myStatus) << 1)

El resultado es myStatus is: ItemStatus.Received .

También puede ir hacia atrás por Enum cambiando el operador bit a bit de << a >> .

myStatus = (ItemStatus)(((int)myStatus) << 1)

El resultado es myStatus: ItemStatus.New .

Siempre debe agregar código para probar una situación "fuera de límites" en ambas direcciones.

Puede comprender más sobre las operaciones bit a bit aquí: http://code.tutsplus.com/articles/understanding-bitwise-operators--active-11301


Funciona hasta "C" ya que no hay respuesta sobre qué devolver después de "D".

[actualización1] : actualizado según la sugerencia de Marc Gravell.

[actualización2] : actualizado de acuerdo con el deseo de husayt - devuelva "A" para el siguiente valor de "D".

public class Program { public static void Main(string[] args) { Console.WriteLine("Next enum of A = {0}", eRatEnumHelper.GetNextEnumValueOf(eRat.A)); Console.WriteLine("Next enum of B = {0}", eRatEnumHelper.GetNextEnumValueOf(eRat.B)); Console.WriteLine("Next enum of C = {0}", eRatEnumHelper.GetNextEnumValueOf(eRat.C)); } } public enum eRat { A = 0, B = 3, C = 5, D = 8 }; public class eRatEnumHelper { public static eRat GetNextEnumValueOf(eRat value) { return (from eRat val in Enum.GetValues(typeof (eRat)) where val > value orderby val select val).DefaultIfEmpty().First(); } }

Resultado

Siguiente enumeración de A = B
Siguiente enumeración de B = C
Siguiente enumeración de C = D
Siguiente enumeración de D = A


Gracias a todos por sus respuestas y comentarios. Me sorprendió tener tantos de ellos. Al verlos y usar algunas de las ideas, se me ocurrió esta solución, que funciona mejor para mí:

public static class Extensions { public static T Next<T>(this T src) where T : struct { if (!typeof(T).IsEnum) throw new ArgumentException(String.Format("Argumnent {0} is not an Enum", typeof(T).FullName)); T[] Arr = (T[])Enum.GetValues(src.GetType()); int j = Array.IndexOf<T>(Arr, src) + 1; return (Arr.Length==j) ? Arr[0] : Arr[j]; } }

Lo mejor de este enfoque, que es simple y universal de usar. Implementado como método de extensión genérico, puede llamarlo en cualquier enumeración de esta manera:

return eRat.B.Next();

Tenga en cuenta que estoy usando un método de extensión generalizado, por lo tanto, no es necesario que especifique el tipo de llamada, simplemente .Next() .

Gracias de nuevo.


Me gustaría ir con la respuesta de Sung Meister, pero aquí hay una alternativa:

MyEnum initial = MyEnum.B, next; for (int i = ((int) initial) + 1, i < int.MaxValue; i++) { if (Enum.IsDefined(typeof(MyEnum), (MyEnum) i)) { next = (MyEnum) i; break; } }

Nota: muchas suposiciones asumidas :)


Para una solución simple, puede extraer una matriz de enum.

eRat[] list = (eRat[])Enum.GetValues(typeof(eRat));

Entonces puedes enumerar

foreach (eRat item in list) //Do something

O encuentra el siguiente artículo

int index = Array.IndexOf<eRat>(list, eRat.B); eRat nextItem = list[index + 1];

Almacenar la matriz es mejor que extraer de enum cada vez que desee el siguiente valor.

Pero si quieres una solución más bella, crea la clase.

public class EnumEnumerator<T> : IEnumerator<T>, IEnumerable<T> { int _index; T[] _list; public EnumEnumerator() { if (!typeof(T).IsEnum) throw new NotSupportedException(); _list = (T[])Enum.GetValues(typeof(T)); } public T Current { get { return _list[_index]; } } public bool MoveNext() { if (_index + 1 >= _list.Length) return false; _index++; return true; } public bool MovePrevious() { if (_index <= 0) return false; _index--; return true; } public bool Seek(T item) { int i = Array.IndexOf<T>(_list, item); if (i >= 0) { _index = i; return true; } else return false; } public void Reset() { _index = 0; } public IEnumerator<T> GetEnumerator() { return ((IEnumerable<T>)_list).GetEnumerator(); } void IDisposable.Dispose() { } object System.Collections.IEnumerator.Current { get { return Current; } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return _list.GetEnumerator(); } }

Crear una instancia

var eRatEnum = new EnumEnumerator<eRat>();

Iterar

foreach (eRat item in eRatEnum) //Do something

MoveNext

eRatEnum.Seek(eRat.B); eRatEnum.MoveNext(); eRat nextItem = eRatEnum.Current;


Parece un abuso de la clase de enumeración para mí, pero esto lo haría (suponiendo que llamar a Siguiente en el último valor provocaría un reinicio):

public static eRat Next(this eRat target) { var nextValueQuery = Enum.GetValues(typeof(eRat)).Cast<eRat>().SkipWhile(e => e != target).Skip(1); if (nextValueQuery.Count() != 0) { return (eRat)nextValueQuery.First(); } else { return eRat.A; } }

Y esto le daría el valor anterior sobre la misma base:

public static eRat Previous(this eRat target) { var nextValueQuery = Enum.GetValues(typeof(eRat)).Cast<eRat>().Reverse().SkipWhile(e => e != target).Skip(1); if (nextValueQuery.Count() != 0) { return (eRat)nextValueQuery.First(); } else { return eRat.D; } }


Probablemente un poco exagerado, pero:

eRat value = eRat.B; eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>() .SkipWhile(e => e != value).Skip(1).First();

o si quieres el primero que sea numéricamente más grande:

eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>() .First(e => (int)e > (int)value);

o para el siguiente más grande numéricamente (haciendo el tipo de nosotros mismos):

eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>() .Where(e => (int)e > (int)value).OrderBy(e => e).First();

Oye, con LINQ como tu martillo, el mundo está lleno de uñas ;-p


Publicación anterior, pero tengo una solución alternativa

//Next with looping public static Enum Next(this Enum input) { Array Arr = Enum.GetValues(input.GetType()); int j = Array.IndexOf(Arr, input) + 1; return (Arr.Length == j) ? (Enum)Arr.GetValue(0) : (Enum)Arr.GetValue(j); } //Previous with looping public static Enum Prev(this Enum input) { Array Arr = Enum.GetValues(input.GetType()); int j = Array.IndexOf(Arr, input) - 1; return (j == -1) ? (Enum)Arr.GetValue(Arr.Length -1) : (Enum)Arr.GetValue(j); }

Y cuando necesites usarlo, solo haz un yeso

BootstrapThemeEnum theme = BootstrapThemeEnum.Info; var next = (BootstrapThemeEnum)theme.Next();

mi enum

public enum BootstrapThemeEnum { [Description("white")] White = 0, [Description("default")] Default = 1, [Description("info")] Info = 2, [Description("primary")] Primary = 3, [Description("success")] Success = 4, [Description("warning")] Warning = 5, [Description("danger")] Danger = 6, [Description("inverse")] Inverse = 7 }


Puedes simplificarlo y generalizarlo:

static Enum GetNextValue(Enum e){ Array all = Enum.GetValues(e.GetType()); int i = Array.IndexOf(all, e); if(i < 0) throw new InvalidEnumArgumentException(); if(i == all.Length - 1) throw new ArgumentException("No more values", "e"); return (Enum)all.GetValue(i + 1); }

EDITAR : tenga en cuenta que si su enumeración contiene valores duplicados (entradas sinónimas), esta ( o cualquier otra técnica enumerada aquí ) fallará, dado uno de esos valores. Por ejemplo:

enum BRUSHSTYLE{ SOLID = 0, HOLLOW = 1, NULL = 1, HATCHED = 2, PATTERN = 3, DIBPATTERN = 5, DIBPATTERNPT = 6, PATTERN8X8 = 7, DIBPATTERN8X8 = 8 }

Dado BRUSHSTYLE.NULL o BRUSHSTYLE.HOLLOW , el valor de retorno sería BRUSHSTYLE.HOLLOW .

<leppie>

Actualización: una versión genérica:

static T GetNextValue<T>(T e) { T[] all = (T[]) Enum.GetValues(typeof(T)); int i = Array.IndexOf(all, e); if (i < 0) throw new InvalidEnumArgumentException(); if (i == all.Length - 1) throw new ArgumentException("No more values", "e"); return all[i + 1]; }

</ leppie>

@leppie :

Su versión genérica le permite a uno pasar accidentalmente un valor no enum, que se capturará solo en tiempo de ejecución. Originalmente lo escribí como un genérico, pero cuando el compilador rechazó where T : Enum , lo saqué y me di cuenta de que no estaba obteniendo mucho de los genéricos de todos modos. El único inconveniente real es que debe devolver el resultado a su tipo de enumeración específico.


Puedo pensar en 2 cosas:

  • eRat.B + 3
  • Enum.Parse (typeof (((int) eRat.B) +3)

Solución LINQ que no se rompe en el último elemento sino que continúa en el valor predeterminado de nuevo:

var nextValue = Enum.GetValues(typeof(EnumT)).Cast<EnumT>().Concat(new[]{default(EnumT)}).SkipWhile(_ => _ != value).Skip(1).First();


var next = (eRat) ((int) someRat + 3);