从另一个方面看 Linq to Xml中的万圣节问题(迭代中的万圣节问题)
2012-04-25 18:46
288 查看
参考:http://blog.csdn.net/lee576/article/details/6333828
对这篇文章的解释表达的不同看法。
发现此大牛也在研究Linq toxml的问题。
直接看代码万圣节问题指在迭代一组元素的时候,
删除或改变元素个数时,迭代出现的的不正常行为,
但这种问题可以避免,同时达到 本来要达到的效果
书中的例子
理论上在foreach的时候,每次都调用remove了,所以每次都应该打印出删除的元素,并且父元素下的子
元素应该全部都删除掉了,可是打印出的结果并非如此
竟然还剩一个元素没有删除掉!并且也只打印出第一个元素
删除掉的那句话。费解吗?其实linq的执行都是延迟执行的,
这是其导致的潜在副作用书中给出的解决方案是,缓存元素序列,
其中用到了 ToArray 操作符(那位阿牛对方给的解释)
我认为他的观点很正确,我开始也是这样认为的。经过我仔细的研究发现了一个问题。
那么element [1] 这个元素就不存在了,Remove[1]没有这个元素,
所以删除不了,剩下了 Ewan-Buckingham,所以Element就还存
在不能删除!!呵呵, 那么ToArray 呢刚好巧妙的将动态的数据变为固定的数组!
xml linq ==>ToArray后。元素不是延迟的,是非延迟操作符。
但是她实际上做的工作是这样的==》
如果你 不这样做。 Elements数组是变化的!
就是说你删了第一个元素,如果里面有2个数
那么 elements只剩下了一个元素===element[0]=EwanBuckingham
继续 Foreach Remove element[1] 不能删除,所以就剩余一个元素了!
我也在仔细看这本书---如过我说错了也欢迎批评指正。
对这篇文章的解释表达的不同看法。
发现此大牛也在研究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 To Xml:迭代中的万圣节问题
- linq to xml 中,html编码的问题
- Linq to XML:查询不到数据的问题
- LINQ To XML:根据一个XML覆盖另一个XML节点内容
- linq to xml 中,html编码的问题
- Linq to XML用XmlReader读取数据导致无法输出的格式化异常的问题
- Linq to XML---网站地图和RSS Feed
- linq to xml之增改删查
- LinqToXml(删除某节点)
- XML基础学习02<linq to xml>
- 使用linq to xml 快速创建自己的Rss
- LINQ to XML 编程基础
- LINQ To XML:遍历元素属性
- linq to xml操作XML
- Linq to XML读取数据库生成XML
- LinqToEntity中.toString()与.toShortDateTime()无法使用的问题解决方式
- 一个实例掌握linq to XML增查删改(转)
- Linq to XML更新CDATA节点的方法
- Linq To Xml 增删改查
- [导入]使用linq to xml 快速创建自己的Rss