2010-05-06 29 views
5

En C#, se puede usar el número de rangos de tipos de enumeración, por ejemploson rangos posibles con enumeraciones?

public enum BookType 
{ 
    Novel = 1, 
    Journal = 2, 
    Reference = 3, 
    TextBook = 4 .. 10 
} 

EDIT: La razón de esto es necesario es para echar a un número al tipo de enumeración, por ejemplo:

int iBook = 5 
BookType btBook = (BookType)ibook 
Debug.Print "Book " + ibook + " is a " btBook 

y el resultado esperado es: libro 5 es un libro de texto

+2

¿Qué valor esperarías tener 'BookType.TextBook'? – Gabe

Respuesta

8

De acuerdo con el estándar C# (p612, El lenguaje de programación C#) el valor dado a una enumeración debe ser un entero constante (o cualquier tipo similar - largo, byte, sbyte, corto, etc.), por lo que un rango de valores no es válido.

Mi compilador (VS2008) está de acuerdo con la especificación.

Como no se puede repetir nombres dentro de una enumeración, la que más se aproxima es algo como esto:

public enum BookType 
{ 
    Novel = 1, 
    Journal = 2, 
    Reference = 3, 
    TextBook4 = 4, 
    TextBook5 = 5, ... 
    TextBook10 = 10 
} 

que en realidad es bastante feo. Tal vez una enumeración no es la solución a su problema en particular ...

+4

Como lo hace la lógica. El objetivo de una enumeración es reemplazar los números mágicos en su código con fragmentos de (con suerte) texto descriptivo. Si se permitieran rangos, ¿cómo sabría el compilador qué número mágico reemplazará su texto enum? – MusiGenesis

+2

No es necesario que sean enteros. puede usar la opción de tipo base para declarar enum cuyos miembros son de tipo long, byte, sbyte, short, ushort, uint, ulong etc. – SysAdmin

+0

@SysAdmin - buen punto. Usé entero en un sentido genérico, en lugar de en32, etc. Enmendaré la respuesta para ser más preciso. – Bevan

1

No, no lo es. Si las constantes numéricas que está tratando de asignar realmente tienen el mismo significado, aún necesitaría un miembro separado para cada constante numérica. Al igual que TextBook4, TextBook5, etc.

0

Quizás quiso hacer una pregunta relacionada, que es: ¿puede tener más de una enumeración (no estoy seguro de que tengo la terminología correcta, pero mi ejemplo será mostrar lo que quiero decir) para cada valor?

En C#, se puede hacer algo como esto:

public enum BookType 
{ 
    Novel = 1, 
    Journal = 2, 
    Magazine = 2, 
    Reference = 3, 
    TextBook = 4, 
    LabWorkbook = 4, 
    Dictionary = 5, 
    Encyclopedia = 5 
} 

De esta manera, se puede utilizar cualquiera BookType.Journal o BookType.Magazine en su código, cualquiera de los cuales es sinónimo del valor 2. Si esto se debe hacer es otro asunto - No estoy familiarizado con los argumentos a favor o en contra de esto (me gustaría decir que "si C# lo permite, debe estar bien", pero eso sería completamente loco).

7

Como han dicho otros, no, no es posible. Es posible combinar valores enum si son indicadores:

[Flags] 
public enum BookType 
{ 
    Novel = 0, 
    Journal = 1 << 0, 
    Reference = 1 << 1, 
    TextBook1 = 1 << 2, 
    TextBook2 = 1 << 3, 
    TextBook3 = 1 << 4, 
    TextBook4 = 1 << 5, 
    TextBook5 = 1 << 6, 
    TextBooks1To5 = TextBook1 | TextBook2 | TextBook3 | TextBook4 | TextBook5 
} 
1

Puede optar por un diccionario en su lugar.

var BookType = new Dictionary<int, string>(); 
BookType.Add(1, "Novel"); 
BookType.Add(2, "Journal"); 
BookType.Add(3, "Reference"); 
BookType.Add(4, "TextBook"); 
BookType.Add(5, "TextBook"); 
BookType.Add(6, "TextBook"); 
BookType.Add(7, "TextBook"); 
BookType.Add(8, "TextBook"); 
BookType.Add(9, "TextBook"); 
BookType.Add(10, "TextBook"); 

int iBook = 5 
Debug.Print "Book " + iBook + " is a " BookType[iBook] 

Editar: También puede declarar su diccionario de sólo lectura si está en el nivel de clase.

Puede usar una enumeración como el valor del diccionario en lugar de la cadena.

3

Un tanto offtopic, puedes simular enumeraciones usando clases normales con campos de solo lectura.

p. Ej. algo similar a éste resolvería su problema:

public sealed class BookType 
{ 
    public static readonly BookType Novel = new BookType(1, 1, "Novel"); 
    public static readonly BookType Journal = new BookType(2, 2, "Journal"); 
    public static readonly BookType Reference = new BookType(3, 3, "Reference"); 
    public static readonly BookType Textbook = new BookType(4, 10, "Textbook"); 

    public int Low { get; private set; } 
    public int High { get; private set; } 
    private string name; 

    private static class BookTypeLookup 
    { 
     public static readonly Dictionary<int, BookType> lookup = new Dictionary<int, BookType>(); 
    } 

    private BookType(int low, int high, string name) 
    { 

     this.Low = low; 
     this.High = high; 
     this.name = name; 

     for (int i = low; i <= high; i++) 
      BookTypeLookup.lookup.Add(i, this); 
    } 

    public override string ToString() 
    { 
     return name; 
    } 

    public static implicit operator BookType(int value) 
    { 
     BookType result = null; 
     if (BookTypeLookup.lookup.TryGetValue(value, out result)) 
      return result; 

     throw new ArgumentOutOfRangeException("BookType not found"); 
    } 
} 

Es un poco más detallado que una enumeración normal, pero permite definir osciló miembros de una enumeración de igual manera.

p. Ej.

var bookType = (BookType)5; 
Console.WriteLine(bookType); 
1

Si se puede asignar a los valores ENUM cadenas de ti mismo, entonces usted puede utilizar algunos bitmagic para asignar múltiples valores int a mismo valor de enumeración. Los subtipos pueden ser enumerados por cada BookType (NovelTypes, JournalTypes, etc.).

En el lado negativo

  • sí requiere alguna modificación valor cuando se lanza a BookType
  • cada rango de subtipo es del mismo tamaño (16 en el ejemplo actual.
  • que es un poco menos legible que sencillo Novel = 3 tipo de mapeo

código Ejemplo:.

class Program 
{ 
    /// <summary> Number of subtypes reserved for each BookType. </summary> 
    private const byte BookTypeStep = 16; 
    /// <summary> Bitmask to use to extract BookType from a byte. </summary> 
    private const byte BookTypeExtractor = Byte.MaxValue - BookTypeStep + 1; 
    /// <summary> Bitmask to use to extract Book subtype from a byte. </summary> 
    private const byte BookSubTypeExtractor = BookTypeStep -1; 

    public enum BookType : byte 
    { 
     Unknown = 0, 
     Novel = BookTypeStep * 1, 
     Journal = BookTypeStep * 2, 
     Reference = BookTypeStep * 3, 
     TextBook = BookTypeStep * 4, 
    } 

    static void Main(string[] args) 
    { 
     for(int i = 16; i < 80; i++) 
     { 
      Console.WriteLine("{0}\tof type {1} ({2}),\tsubtype nr {3}", 
       i, 
       i & BookTypeExtractor, 
       (BookType)(i & BookTypeExtractor), 
       i & BookSubTypeExtractor 
      ); 
     } 
     Console.ReadLine(); 
    } 
} 

Este ejemplo tiene rangos 16-31 de novelas, 32-47 para los diarios, etc.

3

Dado que usted es incapaz de asignar un rango de valores de una enumeración, pensé en un enfoque alternativo con el fin de asignar una enumeración como un valor límite (el ejemplo se basa en el tiempo):

private enum eTiming 
    { 
     eOnTime = 0, 
     eSlightDelay = 5, 
     eMinorDelay = 15, 
     eDelayed = 30, 
     eMajorDelay = 45, 
     eSevereDelay = 60 
    } 

    private static eTiming CheckIfTimeDelayed(TimeSpan tsTime) 
    { 
     eTiming etiming = eTiming.eOnTime; 

     foreach (eTiming eT in Enum.GetValues(typeof(eTiming))) 
     { 
      if (Convert.ToInt16(eT) <= tsTime.TotalMinutes) 
       etiming = eT; 
     } 

     return etiming; 
    } 

Esto es suponiendo que la enumeración se ordena, y trabaja de forma inesperada con firmados - valores().

0

La respuesta más simple a su pregunta es No. La forma más fácil de lograr lo que desea es:

public enum BookType 
{ 
    Novel = 1, 
    Journal = 2, 
    Reference = 3, 
    TextBook = 4 
} 

public void bookOutput(int book) 
{ 
    if(book < 4) 
     Console.Writeline("Book "+book+" is a " + ((BookType)book).ToString()); 
    else 
     Console.Writeline("Book "+book+" is a " + BookType.TextBook.ToString()); 
} 

La idea es dejar que la enumeración sea los valores individuales y manejar la gama con instrucciones lógicas.

Cuestiones relacionadas