Compatibilità di Enum vs. costanti di stringa

4

Recentemente mi è stato detto che usando Enum :

public enum TaskEndState { Error, Completed, Running }

potrebbe avere problemi di compatibilità / serializzazione, e quindi a volte è meglio usare const string:

public const string TASK_END_STATE = "END_STATE";
public const string TASK_END_STATE_ERROR = "TASK_END_STATE_ERROR";
public const string TASK_END_STATE_COMPLETE = "TASK_END_STATE_COMPLETE";
public const string TASK_END_STATE_RUNNING = "TASK_END_STATE_RUNNING";

Riesci a trovare un caso pratico in cui può accadere, ci sono delle linee guida in cui Enum deve essere evitato?

Modifica Il mio ambiente di produzione ha più servizi WFC (diverse versioni dello stesso prodotto). Una versione successiva può / o non può includere alcune nuove proprietà come Stato fine attività (questo è solo un esempio). Se proviamo a deserializzare un nuovo valore Enum in una versione precedente di un servizio specifico, potrebbe non funzionare.

    
posta Yosi Dahari 06.11.2013 - 14:35
fonte

3 risposte

5

Non dici esattamente come stai serializzando il Enum , che è importante qui. Assumerò che lo serializzi come il valore integrale sottostante. In tal caso, il tuo codice attuale ha effettivamente un problema di versione, se aggiungi un nuovo valore nel mezzo di Enum .

Ad esempio, nel tuo codice corrente, Error è 0, Completed è 1 e Running è 2. Ora immagina di aver cambiato il codice in:

public enum TaskEndState { Error, Timeout, Completed, Running }

All'improvviso, ciò che hai salvato come Running (vecchio 2) verrà letto come Completed (nuovo 2), che non è corretto.

Il modo migliore per gestire questo è specificare esplicitamente i valori numerici per ciascun membro enum e non cambiarli mai. È possibile aggiungere nuovi valori laster, ma devono avere un nuovo valore intero. Ad esempio, l'originale:

public enum TaskEndState { Error = 0, Completed = 1, Running = 2 }

E la versione modificata:

public enum TaskEndState { Error = 0, Timeout = 3, Completed = 1, Running = 2 }
    
risposta data 06.11.2013 - 16:33
fonte
0

Non esiste una risposta giusta per questa domanda. Si riduce a quanto esplicito vuoi che il contratto sia.

Da un lato, puoi inviare questi dati semplicemente come un xsd:string elemento chiamato TaskEndState . Qui, il contratto prende qualsiasi stringa nel messaggio. La convalida dovrà essere eseguita in codice per verificare che la stringa inviata nel messaggio corrisponda a un valore noto nel codice. Nuovi codici possono essere aggiunti senza modificare il contratto. Questo è un contratto meno esplicito. Questo tipo di contratto è più flessibile da modificare, ma la convalida non viene più eseguita esclusivamente a livello di schema poiché alcune convalide dovranno verificarsi all'interno del codice.

D'altra parte, puoi definire una restrizione (enumerazione) sull'elemento xsd:string che prenderà solo i valori definiti. La convalida avverrà solo a livello di schema. Nuovi codici possono essere aggiunti, ma questo cambia il contratto. Questo è il contratto esplicito. Questo tipo di contratto è meno flessibile da modificare, ma la convalida viene comunque eseguita in un unico posto, a livello di schema. In alcuni casi questo è auspicabile perché la convalida dello schema viene eseguita in ubicazioni centralizzate e il consenso generale è che la convalida del messaggio sia separata dall'elaborazione effettiva del messaggio. Tuttavia, poiché il contratto è cambiato, i chiamanti dovranno riesaminare e verificare che le restrizioni aggiuntive non abbiano infranto nulla.

In generale, di solito vado con le enumerazioni perché mi piace che i miei contratti siano espliciti il più possibile. Ma non ci sono assoluti.

Nel tuo caso, se le nuove stringhe non vengono aggiunte così spesso, andrei con l'enum. Se i dati di TaskEndState sono molto volatili (cambiano costantemente) andrei con la stringa generica.

Ci sono alcuni buoni articoli online su come gestire le restrizioni. Ecco uno di questi link:

link

    
risposta data 06.11.2013 - 16:26
fonte
-1

Per la gestione della compatibilità, enum vs string è un'aringa rossa: l'app ha una certa comprensione della versione dello schema del "documento di dati" o meno. Se lo fa, allora questo è un dettaglio di implementazione piuttosto banale. Se non hai lo stesso problema in ogni caso.

Come gestirlo con WCF è rendere lo strato di facciata pubblica un involucro sottile che alimenta i documenti di dati con alcune notazioni di versione in interni che possono gestirli correttamente. Un sacco di modi per arrivare a "gestirlo correttamente" e molto dipende dalle specifiche della tua app, quindi non posso dare una risposta adeguata a questa domanda qui.

    
risposta data 06.11.2013 - 15:30
fonte

Leggi altre domande sui tag