2009-07-24 4 views
5

OK, quindi ho un campo di database di tipo char (1) che ha un piccolo numero di possibili codici di stato (ad esempio 'F' = Fallimento, 'U' = Sconosciuto, ecc.). Mi piacerebbe avere una classe enum C# che corrisponda a questi stati. Posso fare:Come implementare C enum en per il campo del database char (1) enumerato?

public enum StatusCode : byte { 
    Unknown = (byte) 'U', 
    Failure = (byte) 'F', 
    // etc. 
} 

Fin qui tutto bene. Ma nel DataTable restituito dal database, i valori delle colonne sono istanze System.Data.SqlTypes.SqlString. Ci sono ovviamente alcuni problemi nel convertire da una stringa C# (o anche un carattere C#) in un byte C# (poiché C# char è in realtà un codepoint UTF-16). Ma in questo caso so che i valori sono vincolati a un piccolo insieme e il codice dovrebbe generare un'eccezione se un valore esterno a questo set passa.

Con questo in mente, qual è il modo migliore per farlo? È sicuro lanciare da un SqlString a un byte? Convert.ToByte() sarebbe migliore? Sarebbe meglio usare semplicemente un costrutto switch/case per attraversare i valori nell'enum?

Sto cercando il modo "migliore" per farlo, non solo in termini di risultati corretti ma anche di chiarezza del codice. Suppongo che potrei anche semplicemente usare alcune costanti come

public const char UnknownStatus = 'U'; 
public const char FailureStatus = 'F'; 

Ma preferisco usare un enum, se possibile. qualche idea?

Modifica: per chiarire che cosa voglio fare fare con questo, mi aspetto di utilizzare questi valori frequentemente attraverso il mio codice. Ad esempio, voglio essere in grado di fare cose come:

public void DoSomething(StatusCode currentStatus) { 
    if(currentStatus == StatusCode.Failure) { 
     throw new SomeException(); 
    } 

    switch(currentStatus) { 
     case StatusCode.Unknown: 
      // do something 
      break; 
    } 
} 

E così via. In particolare mi voglio evitare cose come:

public void DoSomething(char currentStatus) { 
    if(currentStatus == 'F') { 
     // do something 
    } 
} 

Poiché in questo caso sto usando cosa s'intenda per "numeri magici" in tutto il luogo. In particolare, ciò renderebbe praticamente impossibile la migrazione verso un altro sistema di segnalazione dello stato. Ha senso?

+0

Vedi anche http://stackoverflow.com/questions/1167927/syncing-referential-integrity-tables-and-enums e http://stackoverflow.com/questions/1015058/enum-storage-in- database-field, e in generale, http://stackoverflow.com/search?q=enum%20database&tab=newest –

risposta

5

Forse un oggetto "costante"?

public sealed class StatusCode { 
    private char value; 

    public static readonly StatusCode Unknown = new StatusCode('U'); 
    public static readonly StatusCode Failure = new StatusCode('F'); 

    private StatusCode(char v) { 
     value = v; 
    } 

    public override string ToString() { 
     return value.ToString(); 
    } 

} 

Poi, più avanti nel codice, si potrebbe usare come un enum: StatusCode.Unknown. È anche possibile fornire un metodo interno per "analizzare" un valore ricevuto in un oggetto di StatusCode.

+2

dovresti fornire uguaglianza implicita per fornire un confronto corretto per determinati valori ... –

+0

Esatto! : D – Fernando

+0

OK, penso che questa sia la strada che sto per percorrere. Sfortunatamente, le dichiarazioni del caso continuano a non funzionare come vorrei, ma almeno tutto il resto lo fa. (Proprio come il vecchio stile enum Java!) –

0

Se siete su .NET 2.0 e versioni successive, è possibile implementare questo utilizzando un dizionario generico:

Dictionary<char,string> statusCode = new Dictionary<char,string>(); 
statusCode.Add('U', "Unknown"); 
statusCode.Add('F', "Failure"); 

o in alternativa:

Dictionary<char,StatusCode> statusCode = new Dictionary<char,StatusCode>(); 
statusCode.Add('U', StatusCode.Unknown); 
statusCode.Add('F', StatusCode.Failure); 

e si poteva accedere alla rappresentazione di stringa per un dato codice in questo modo:

string value = statusCode['A']; 

o

StatusCode myCode = statusCode['A']; 

e così via. Dovresti riempire quel dizionario dai valori del database, o da qualche tipo di file di configurazione o qualcosa del genere.

Marc

0

Sarebbe qualcosa di simile a questo lavoro per voi?

public Enum StatusCode : int{ 
    [StringValue("U")] 
    Unknown =0, 
    [StringValue["F"] 
    Failuer=1 
} 
+0

è la tua parte Attributo StringValue del framework .NET? Una rapida ricerca su Google mostra un paio di classi con quel nome ma nulla su MSDN – STW

+0

http://weblogs.asp.net/stefansedich/archive/2008/03/12/enum-with-string-values-in-c.aspx ha un esempio completo di implementazione. – JasonTrue

1

Skip modificare Hai provato questo (che non funziona come aver controllato e commentato):

public enum StatusCode : char 
{ 
    Failure = 'F', 
    Unknown = 'U', 
    ... 
} 

EDIT - soluzione corretta
o del presente (forse anche provare con una struct):

public sealed class StatusCode 
{ 
    public static readonly char Failure = 'F'; 
    public static readonly char Unknown = 'U'; 
    ... 
    public char Value { get; set; } 
} 

il codice che hai fornito sarebbe wor k in questo modo:

public void DoSomething(StatusCode currentStatus) { 
    if(currentStatus.Value == StatusCode.Failure) { 
     throw new SomeException(); 
    } 

    switch(currentStatus.Value) { 
     case StatusCode.Unknown: 
      // do something 
      break; 
    } 
} 

Se non ti piace utilizzare Value proprietà si può sempre implementare operatore di uguaglianza implicita tra StatusCode e char tipi. In tal caso, il tuo codice non cambierebbe un po '.

+0

Non valido: il compilatore fornisce: Errore Tipo byte, sbyte, breve, ushort, int, uint, long, o ulong expecte –

+2

Ehi, ora, nessuna ragione per portare parolacce in questo. ;-) –

+0

^^ Mi mancava quasi quello! : D – Jagd

0

Se si dispone di una tabella denominata StatusCode che include una chiave primaria intera, è possibile utilizzarla come identificatore e collegarla alla logica. E in tal caso, l'enum sarebbe la cosa migliore da usare. Anche se non sono sicuro che sia fattibile per te.

0

Una possibilità è quella di impostare l'enum con nomi identici ai valori nel database, come ad esempio:

enum StatusCode 
{ 
    /// <summary>Unknown</summary> 
    U = 0, 
    /// <summary>Failure</summary> 
    F, 
    /// <summary>Etc</summary> 
    E 
} 

Quindi utilizzare un metodo statico per convertire i valori char a un valore enumerato

private StatusCode CharToEnum(string statusCodeChar) 
    { 
     foreach (FieldInfo fi in typeof(StatusCode).GetFields()) 
     { 
      if (fi.Name == statusCodeChar) return (StatusCode)fi.GetValue(null); 
     } 

     return StatusCode.U; 
    } 
0

Breve e dolce mio amico .. Fa tutto il necessario. Non dovresti aver bisogno di usare enum perché non ti serve per assegnare un valore interno ai tuoi stati possibili, conosci già i valori dei tuoi stati.

public sealed class StatusCode 
{ 
    public const string Unknown= "U"; 
    public const string Failure= "F"; 
    public const string Success= "S"; 
} 
Problemi correlati