2009-04-22 7 views
1

Je lisais this article, où ils ont ce code:La désérialisation nécessite un casting?

// Serialization 
XmlSerializer s = new XmlSerializer(typeof(ShoppingList)); 
TextWriter w = new StreamWriter(@"c:\list.xml"); 
s.Serialize(w, myList); 
w.Close(); 

// Deserialization 
ShoppingList newList; 
TextReader r = new StreamReader("list.xml"); 
newList = (ShoppingList)s.Deserialize(r); 

est la dernière ligne une déclaration de casting? Si oui, cela ne dégrade-t-il pas les performances de sérialisation?

Répondre

6

Oui, la dernière ligne est une instruction cast. Le casting a un coût associé mais il est insignifiant par rapport au coût de la sérialisation. Je doute qu'il apparaisse même sur un profiler.

Pensez à ce que la sérialisation implique.

  • traitement d'un flux d'octets
  • Création de types en fonction des métadonnées
  • Conversion entre tableaux d'octets et les types de données

Chacune de ces opérations sont beaucoup plus cher qu'une opération de coulée unique.

EDIT Pourquoi cela nécessite-t-il un moulage?

Il y a plusieurs raisons à cela. La première est que les API de désérialisation n'ont aucun moyen de savoir quel est le type du flux d'octets avant de l'inspecter. Le seul choix de l'API en termes de type de retour dans les métadonnées est donc Object. Deuxièmement, la désérialisation doit supporter littéralement n'importe quel type sérialisable. Pour fonctionner, il doit choisir un type de retour pour la méthode applicable à tous les types qui peuvent être sérialisés. Le seul type disponible qui répond à cela est l'objet.

+0

Merci Jared. La raison pour laquelle je me demandais est parce que je veux utiliser la sérialisation pour mon système de fichiers de sauvegarde dans mon application, mais les fichiers peuvent contenir des millions d'objets. Savez-vous pourquoi cela nécessite une distribution? c'est à dire. pourquoi n'est-il pas sûr de type? –

+2

@Joan nécessite une conversion, car le moteur de désérialisation ne connaît pas le type avant de lire les données sous-jacentes. De plus, l'API existe depuis avant les génériques, elle a donc été obligée de renvoyer un objet en tant que type. – JaredPar

+0

Merci Jared, bon à savoir. Alors est-il possible d'avoir un sérialiseur qui retourne le type sans casting? –

3

Les moules sont extrêmement bon marché comparé au coût de désérialisation lui-même. Le processus de désérialisation est assez complexe - un seul casting (de travail) prend à peine du temps.

Bien sûr, si vous êtes intéressé par sérialisation rapide, portable, compact avec une bonne histoire de versioning, vous devriez regarder Protocol Buffers:

(Il y a d'autres sérialisation fr ameworks aussi, par exemple Thrift.)

+0

Merci Jon. Je ne suis pas sûr de savoir comment fonctionne la sérialisation sous le capot. Savez-vous pourquoi cela nécessite une distribution? c'est à dire. pourquoi n'est-il pas sûr de type? –

+1

Regardez le type de retour de l'API - qui a été créé avant les génériques. Il n'y a vraiment pas grand chose à faire pour éviter cela. –

+0

Merci Jon. Alors est-il possible d'avoir un sérialiseur qui retourne le type sans casting? Juste par curiosité :) –

0

Deserialize renvoie un type Object de sorte que la conversion soit effectuée dans la bonne classe.

Si cela aurait un impact sur la désérialisation ou non, vous voulez que cela fasse partie de ShoppingList.

1

La méthode Deserialize() renvoie un objet et doit être "cast" dans le type correct.

La diffusion indique principalement au compilateur que vous connaissez le type d'objet car le compilateur ne peut pas en déduire son type.L'exécution génère toujours une exception InvalidCast si le type n'est pas celui que vous avez spécifié (ou un sous-type du type spécifié).

Le coût réel du moulage est minime.

+0

Je ne suis pas d'accord avec votre affirmation concernant l'inférence du type. Il n'essaie même pas de déduire le type car la sérialisation était en .NET bien avant les génériques. – Samuel

+0

Je vous entends. Je pense que je parle en termes très généraux.Nous avons casté car le type à runtine est inconnu du compilateur (au moment de la compilation). Peut-être pas une utilisation correcte du terme «déduire». – andleer

0

Si vous changez cette dernière ligne de code

newList = (ShoppingList)s.Deserialize(r); 

à

newList = s.Deserialize(r); 

Le compilateur ajoutera de nouveau dans un plâtre. Je viens de le confirmer avec .NET Reflector de Red Gate. Donc, quel que soit le coût de la distribution, vous devez le faire si vous voulez utiliser cet objet typé.