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

      参考: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]
不能删除,所以就剩余一个元素了!
我也在仔细看这本书---如过我说错了也欢迎批评指正。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值