2010-02-11 9 views
12

Considerate due istanze di una classe, è una pratica buona e affidabile confrontarle prima serializzandole prima e confrontando quindi matrici di byte (o possibilmente hash di matrici). Questi oggetti potrebbero avere proprietà gerarchiche complesse, ma la serializzazione dovrebbe essere profonda quanto necessario.È affidabile confrontare due istanze di una classe confrontando i loro array di byte serializzati?

Per confronto intendo il processo di fare in modo che tutte le propertis dei tipi primitivi abbiano valori uguali, le proprietà dei tipi complessi abbiano le stesse proprietà dei tipi primitivi, ecc. Come per le proprietà di raccolta, devono essere uguali tra loro: uguali elementi, stesse posizioni:

{'a','b','c'} != {'a','c','b'} 



{new Customer{Id=2, Name="abc"}, new Customer {Id=3, Name="def"}} 
    != 
{new Customer{Id=3, Name="def"}, new Customer {Id=2, Name="abc"}} 

ma

{new Customer{Id=2, Name="abc"}, new Customer {Id=3, Name="def"}} 
    == 
{new Customer{Id=2, Name="abc"}, new Customer {Id=3, Name="def"}} 

E per la serializzazione intendo standard di formattatore binario NET.

Grazie.

+1

Per quale scopo vorresti fare questo tipo di confronto? Questo potrebbe aiutare a fornire una risposta più dettagliata. – BlueMonkMN

+0

Attualmente conosco due modi di confrontare gli oggetti (quelli che non implementano IComparable o IEquattable), con PropertyInfo e PropertyDescriptor. Questo potrebbe essere semplicemente un terzo strumento nel mio toolkit. Ma mi interessa l'applicabilità generale e l'affidabilità di questo metodo. Può dare risultati sbagliati? – Valentin

risposta

5

Si sta richiedendo una garanzia che la rappresentazione serializzata corrisponda. Sarà terribilmente difficile da trovare, BinaryFormatter è una classe complicata. Strutture particolarmente serializzate che hanno l'imbottitura di allineamento potrebbero essere un potenziale problema.

Ciò che è molto più semplice è fornire un esempio in cui non corrisponderà. System.Decimal ha diversi modelli di byte per valori come 0.01M e 0.010M. Il suo operatore ==() dirà che sono uguali, il suo byte serializzato [] non lo farà.

2

Si dovrebbe definire che cosa significa uguale qui ancora più precisamente.

Se una delle proprietà è una raccolta, potrebbero esserci differenze nell'ordine (come risultato di determinate sequenze Aggiungi/Rimuovi) che potrebbero essere significative o meno per voi. Pensa a un dizionario in cui gli stessi elementi sono stati aggiunti in un ordine diverso. Una collisione potrebbe causare un flusso binario diverso.

2

È affidabile se:

  1. Ogni singola classe nel grafico è segnato [Serializable]. Questo non è così semplice come potrebbe sembrare; se stai confrontando oggetti totalmente arbitrari, allora c'è una buona possibilità che ci sia qualcosa di non serializzabile in cui non hai il controllo.

  2. Si desidera sapere se le due istanze sono esattamente . Tieni presente che lo BinaryFormatter si sta essenzialmente tuffando nello stato interno di questi oggetti, quindi anche se sembrano essere gli stessi in virtù delle proprietà pubbliche, potrebbero non esserlo. Se sai per certo che il grafico è stato creato esattamente nello stesso modo in ogni caso, forse non ti importa di questo; ma in caso contrario, potrebbe esserci un numero di differenze nascoste tra i grafici.

    Questo punto è anche una ruga più seria di quanto si possa sospettare prima. Cosa succede se decidi di sostituire la classe con un'interfaccia? Potresti avere due interfacce che, per quanto ne sai, sono esattamente le stesse; svolgono lo stesso compito e forniscono gli stessi dati. Ma potrebbero essere implementazioni totalmente diverse. La cosa bella di IEquatable è che è indipendente dal tipo di calcestruzzo.

quindi questo sarà lavoro, per un numero significativo di casi, ma probabilmente non lo considererei una buona pratica, almeno non senza conoscere tutti i dettagli circa il contesto specifico che è utilizzato in Per lo meno, non fare affidamento su questo come metodo di confronto generico per qualsiasi due istanze; dovrebbe essere usato solo in casi specifici in cui si conoscono i dettagli di implementazione delle classi coinvolte.

Ovviamente, alcuni potrebbero dire che scrivere qualsiasi codice che dipende dai dettagli di implementazione di una classe è sempre una pratica scorretta.La mia opinione su questo è più moderata, ma è qualcosa da considerare: basarsi sui dettagli di implementazione di una classe può portare a un codice difficile da gestire in seguito.

+0

Per quanto riguarda il punto 1), un tipo non serializzabile nel grafico genererà un'eccezione. –

Problemi correlati