2010-03-23 3 views
1

Est-ce que quelqu'un sait pourquoi NetDataContractSerializer peut ajouter des entrées "nil" dans une collection sérialisée?Quelles sont toutes ces entrées de collection null dans mon XML DataContract?

Par exemple,

<Jobs z:Id="17"> 
    <_items z:Id="18" z:Size="4"> 
     <JobRecord z:Id="19"> 
     <Name z:Id="20">Job1</Name> 
     </JobRecord> 
     <JobRecord i:nil="true" /> 
     <JobRecord i:nil="true" /> 
     <JobRecord i:nil="true" /> 
    </_items> 
    <_size>1</_size> 
    <_version>2</_version> 
    </Jobs> 

Remarquez les trois entrées « JobRecord » supplémentaires et l'élément supplémentaire en disant « hey, je sais qu'il ya quatre nœuds ici, mais seulement l'un d'entre eux signifie quoi que ce soit. »

Cela semble être un comportement étrange. Ok, je pouvais voir que le NDCS s'intègre profondément dans le graphe d'objets et pourrait se tourner vers un tableau de sauvegarde dont la taille est supérieure au nombre d'éléments en sérialisation (pensez au tableau de sauvegarde pour une liste).

Est-ce que c'est ce qui se passe ici? Est-ce un artefact de la classe que le constructeur crée pour gérer yield return (qui est la source du JobRecord)?

+1

Pourriez-vous montrer le code qui sérialise ceci? Vous parlez de "rendement de rendement", mais on ne sait pas comment cela se rapporte à ce XML. –

Répondre

1

Les collections et les listes .net fonctionnent par redimensionnement automatique lorsqu'elles manquent d'espace. Pour rendre cela efficace, ils ne se contentent pas de redimensionner de 1 en plus chaque fois qu'ils sont épuisés, ils utilisent un algorithme interne pour redimensionner et laisser de l'espace supplémentaire, le but étant qu'ils ne doivent pas être redimensionnés trop souvent.

Ce que vous voyez ici est la collection sérialisée avec tout l'espace supplémentaire étant sérialisé aussi. c'est parce que la sérialisation stocke la collection exactement comme elle est, donc quand vous la désérialisez, vous obtenez la même chose, avec le même nombre d'espace interne.

S'il s'agit d'une liste que vous utilisez, vous pouvez vérifier l'espace réservé en interne en consultant la propriété Capacity.

Si vous souhaitez supprimer de l'espace supplémentaire avant de sérialiser la collection, vous pouvez appeler.

myStuff.Capacity = myStuff.Count; 

Ceci va définir la capacité disponible comme étant le même que le nombre d'éléments contenus, donc il n'y aura pas d'espace réservé.

Malheureusement, si c'est une collection que vous utilisez, la capacité n'est pas disponible, il vous suffit de faire confiance à la collection pour qu'elle soit redimensionnée en interne.

De toute façon, je ne m'inquiéterais pas trop à moins que vous ayez besoin d'être vraiment très efficace. Si vous le faites, utilisez plutôt un tableau de taille fixe.

+0

J'utilise tout ce que le compilateur met dans la classe qui implémente 'yield return'. Je ne pensais pas qu'il contiendrait un tableau de mon type de retour. Cela semble toujours un comportement très étrange. Je pense que le sérialiseur déclencherait l'énumérateur, attraperait le résultat et le collerait dans un tableau ou une pile de taille appropriée, puis l'enverrait sur le fil. – Will

+0

@Will. Pouvez-vous poster le code que vous utilisez pour sérialiser cela. Je suis intéressé par la façon dont vous utilisez le rendement. –

+0

Je pense que la vraie réponse est que le NDCS jette un coup d'oeil derrière les rideaux lors de la sérialisation, donc il frappe réellement les internes de la collection et sérialiser ceux-ci. – Will

0

Juste une supposition, mais notez le z:Size="4". On dirait que quatre JobRecord entrées pour moi, et je suppose que trois d'entre eux = null.

+0

Whoa! C'est exactement ce que j'ai dit dans la question! Vous comprenez bien la lecture! Maintenant, * pourquoi le NDCS fait-il cela? * – Will

+0

@Will: ne réalisait pas que vous vouliez dire l'attribut quand vous avez parlé de l'élément supplémentaire. Il le fait pour que vous puissiez désérialiser ce que vous avez sérialisé, bien sûr. –

Questions connexes