views:

38

answers:

2

Can anyone explain why the original address XElement street node changes? It looks like customer1 holds a reference to the address XElement but customer2 and customer3 have taken copies.

Why did the original address change? (LINQPad example)

var address =
    new XElement ("address",
        new XElement ("street", "Lawley St"), 
        new XElement ("town", "North Beach")
    );

var customer1 = new XElement ("customer1", address);
var customer2 = new XElement ("customer2", address);
var customer3 = new XElement ("customer3", address);

customer1.Element ("address").Element ("street").Value = "Another St";

Console.WriteLine (customer2.Element ("address").Element ("street").Value);
Console.WriteLine ();

address.Dump();
Console.WriteLine ();

customer1.Dump();
Console.WriteLine ();

customer2.Dump();
Console.WriteLine ();

customer3.Dump();

OUTPUT

Lawley St


<address>
  <street>Another St</street>
  <town>North Beach</town>
</address> 


<customer1>
  <address>
    <street>Another St</street>
    <town>North Beach</town>
  </address>
</customer1> 


<customer2>
  <address>
    <street>Lawley St</street>
    <town>North Beach</town>
  </address>
</customer2> 


<customer3>
  <address>
    <street>Lawley St</street>
    <town>North Beach</town>
  </address>
</customer3> 
+4  A: 

From the question:

It looks like customer1 holds a reference to the address XElement but customer2 and customer3 have taken copies.

Yes, that's exactly what happens. From the docs for XElement contents:

When adding XNode or XAttribute objects, if the new content has no parent, then the objects are simply attached to the XML tree. If the new content already is parented and is part of another XML tree, then the new content is cloned, and the newly cloned content is attached to the XML tree.

In the first case, address has no parent so it's attached directly. Afterwards, it does have a parent, so it's cloned first.

Jon Skeet
+1  A: 

The same XElement cannot be in multiple trees. You can certainly have multiple references to the same XElement in a particular tree, but the same XElement cannot be in multiple trees.

To customer1, you really and truly added that address XElement. By the time you "added" it to customer2, the actual address1 XElement could not really be added, because it's already a node in another XElement. Since it could not add the original address as a node, the XElement constructor places a clone of that XElement in customer2 and customer3. You now have three equivalent "address" XElements.

Patrick Karcher