您的位置:首页 > 其它

从另一个方面看 Linq to Xml中的万圣节问题(迭代中的万圣节问题)

2012-04-25 18:46 288 查看
      参考:http://blog.csdn.net/lee576/article/details/6333828

对这篇文章的解释表达的不同看法。

      发现此大牛也在研究Linq toxml的问题。 

   直接看代码万圣节问题指在迭代一组元素的时候,

   删除或改变元素个数时,迭代出现的的不正常行为,

   但这种问题可以避免,同时达到 本来要达到的效果

 

书中的例子

  new XElement("BookParticipants",
new XElement("BookParticipant",
new XAttribute("type", "Author"),
new XElement("FirstName", "Joe"),
new XElement("LastName", "Rattz")),
new XElement("BookParticipant",
new XAttribute("type", "Editor"),
new XElement("FirstName", "Ewan"),
new XElement("LastName", "Buckingham"))));

IEnumerable<XElement> elements =
xDocument.Element("BookParticipants").Elements("BookParticipant");

foreach (XElement element in elements)
{
Console.WriteLine("Source element: {0} : value = {1}",
element.Name, element.Value);
}

foreach (XElement element in elements)
{
Console.WriteLine("Removing {0} = {1} ...", element.Name, element.Value);
element.Remove();
}
Console.WriteLine(xDocument);


理论上在foreach的时候,每次都调用remove了,所以每次都应该打印出删除的元素,并且父元素下的子

元素应该全部都删除掉了,可是打印出的结果并非如此
Source element: BookParticipant : value = JoeRattz
Source element: BookParticipant : value = EwanBuckingham
Removing BookParticipant = JoeRattz ...
<BookParticipants>
<BookParticipant type="Editor">
<FirstName>Ewan</FirstName>
<LastName>Buckingham</LastName>
</BookParticipant>
</BookParticipants>


 

      竟然还剩一个元素没有删除掉!并且也只打印出第一个元素

 删除掉的那句话。费解吗?其实linq的执行都是延迟执行的,

  这是其导致的潜在副作用书中给出的解决方案是,缓存元素序列,

  其中用到了 ToArray 操作符(那位阿牛对方给的解释
XDocument xDocument = new XDocument(
new XElement("BookParticipants",
new XElement("BookParticipant",
new XAttribute("type", "Author"),
new XElement("FirstName", "Joe"),
new XElement("LastName", "Rattz")),
new XElement("BookParticipant",
new XAttribute("type", "Editor"),
new XElement("FirstName", "Ewan"),
new XElement("LastName", "Buckingham"))));

IEnumerable<XElement> elements =
xDocument.Element("BookParticipants").Elements("BookParticipant");

foreach (XElement element in elements)
{
Console.WriteLine("Source element: {0} : value = {1}",
element.Name, element.Value);
}

foreach (XElement element in elements.ToArray())
{
Console.WriteLine("Removing {0} = {1} ...", element.Name, element.Value);
element.Remove();
}

Console.WriteLine(xDocument);


      我认为他的观点很正确,我开始也是这样认为的。经过我仔细的研究发现了一个问题。

foreach( element in Elements)
{
里面就是Remove
}
实际上在执行中是这样的,
Remove [0]  Remove[1];
    因为这个Elements是变化的,就是说 删除了第一个 JoeRattor后。

  那么element [1] 这个元素就不存在了,Remove[1]没有这个元素,

所以删除不了,剩下了 Ewan-Buckingham,所以Element就还存

在不能删除!!呵呵,  那么ToArray 呢刚好巧妙的将动态的数据变为固定的数组!

xml linq ==>ToArray后。元素不是延迟的,是非延迟操作符。

但是她实际上做的工作是这样的==》

element[0] = JoeRattz
element[1]=EwanBuckingham
这样去 remove的话肯定都move 干净了!

如果你 不这样做。 Elements数组是变化的!

就是说你删了第一个元素,如果里面有2个数

element[0] = JoeRattz
element[1]=EwanBuckingham
   删除了 joeRattz 
那么 elements只剩下了一个元素===element[0]=EwanBuckingham 

继续 Foreach Remove element[1] 不能删除,所以就剩余一个元素了!

我也在仔细看这本书---如过我说错了也欢迎批评指正。


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linq xml 工作