2013-08-09 15 views
10

In C#, se definiamo un enum che contiene un membro corrispondente a un valore negativo e quindi iteriamo sopra i valori di enum, il valore negativo non viene prima ma ultimo. Perché succede? In altre lingue (C, C++, Ada, ecc.), L'iterazione su un enum ti darà l'ordine in cui l'hai definito.Perché i membri enum negativi sono enumerati per ultimi?

MSDN ha una buona example of this behavior:

using System; 

enum SignMagnitude { Negative = -1, Zero = 0, Positive = 1 }; 

public class Example 
{ 
    public static void Main() 
    { 
     foreach (var value in Enum.GetValues(typeof(SignMagnitude))) 
     { 
      Console.WriteLine("{0,3}  0x{0:X8}  {1}", 
           (int) value, ((SignMagnitude) value)); 
     } 
    } 
} 

// The example displays the following output: 
//   0  0x00000000  Zero 
//   1  0x00000001  Positive 
//  -1  0xFFFFFFFF  Negative 
+2

Probabilmente viene selezionato come non firmato. – SLaks

+4

L'hai fatto [* un * passo oltre rispetto a molti programmatori] (http://stackoverflow.com/questions/18095665/a-lambda-expression-with-a-statement-body-cannot-be-converted-to-an -expression-t/18095816 # comment26488750_18095816) facendo riferimento alla documentazione. La prossima volta, leggilo: "Gli elementi dell'array sono ordinati in base ai valori binari delle costanti di enumerazione (** cioè, per la loro magnitudine senza segno **)." – jason

+0

Dallo stesso articolo [MSDN] (http://msdn.microsoft.com/en-us/library/system.enum.getvalues.aspx): "Gli elementi dell'array sono ordinati in base ai valori binari delle costanti di enumerazione (cioè con la loro grandezza senza segno). " – natenho

risposta

15

Da the very documentation page you link to, il corsivo è mio:

Gli elementi dell'array sono ordinate per i valori binari delle costanti di enumerazione (vale a dire, per la loro senza valore grandezza).

Scavando nel codice CLR (lo SSCLI 2.0) e ottenere di livello inferiore di gran lunga di quanto mi sono davvero confortevole con, sembra che in ultima analisi, questo è dovuto al fatto internamente valori enum sono memorizzati in qualcosa che assomiglia a questo (nota questo è C++):

class EnumEEClass : public EEClass 
{ 
    friend class EEClass; 

private: 

    DWORD   m_countPlusOne; // biased by 1 so zero can be used as uninit flag 
    union 
    { 
     void  *m_values; 
     BYTE  *m_byteValues; 
     USHORT  *m_shortValues; 
     UINT  *m_intValues; 
     UINT64  *m_longValues; 
    }; 
    LPCUTF8   *m_names; 

Come si può vedere, è senza segno tipi che contengono i valori effettivi - in modo che quando questi valori vengono emessi per il conteggio, naturalmente sono nella loro senza segno ordine.

+8

È interessante notare che questo è iniziato come un bug (http://connect.microsoft.com/VisualStudio/feedback/details/98147/enum-getvalues). Se si guardano le versioni precedenti della documentazione prima delle 3.5 non c'è alcuna menzione ufficiale che usasse la loro grandezza senza segno. A causa dell'impossibilità di risolverlo senza rompere le applicazioni esistenti, immagino che abbiano appena aggiornato i documenti: D – keyboardP

+1

Grazie a @keyboardP, è quello che stavo chiedendo davvero. – gmletzkojr

+1

Buona risposta. Tuttavia, presuppone che il lettore sappia in che modo sono rappresentati i numeri negativi (in realtà [complemento a due] (http://en.wikipedia.org/wiki/Signed_number_representation), sebbene la [C# spec] (http: //www.ecma- international.org/publications/standards/Ecma-334.htm) non richiede esplicitamente questo metodo per rappresentare interi con segno).Questa conoscenza è necessaria per capire perché trattarli come non firmati li fa seguire dopo numeri positivi. – stakx

Problemi correlati