Je vote : c'est pas possible en utilisant simplement XmlSerialize.
Ce qui fait que tes deux objets sont identiques, c'est le hashcode (voir GetHashCode()) que colle .Net à chaque objet différent.
Tes 2 objets sont le même pask'ils ont le même hashcode. Mais quand tu les sérialize, tu les "aplati" : tu choppes que les données brut. Le hashcode n'est pas stocké (et heureusement), pask'il est dynamique, et dépend de chaque exécution.
Pour abréger : sérializer, ça transforme un objet en un "paquet de donées".
Ta sérialization transforme donc tes références croisées en "paquets de données" distinct avec un contenu identique.
Donc quand tu désérialize, très logiquement il te recréé deux objets différents.
Solutions :
1 - Rajouter un paramètre ID dans tes objets, faire la désérialization à la main, objet par objet, et quand tu tombes sur un ID déjà désérializé, retourner une référence au lieu d'une nouvelle instance.
2 - Utiliser une autre structure de donnée. Genre d'un côté les données brutes (les instances sans références croisées) et de l'autre leur rangement (l'ordre dans lequel les coller dans le tableau et les références croisées éventuelles).
Bon y'a ptet mieux, mais faudrait voir le code...
---------------
Tout est normal, suffit de comprendre pourquoi.