次のコードを検討してください。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(@"<Parts>
<Part name=""DisappearsOk"" disabled=""true""></Part>
<Part name=""KeepMe"" disabled=""false""></Part>
<Part name=""KeepMe2"" ></Part>
<Part name=""ShouldBeGone"" disabled=""true""></Part>
</Parts>");
XmlNode root = xmlDoc.DocumentElement;
List<XmlNode> disabledNodes = new List<XmlNode>();
try
{
foreach (XmlNode node in root.ChildNodes.Cast<XmlNode>()
.Where(child => child.Attributes["disabled"] != null &&
Convert.ToBoolean(child.Attributes["disabled"].Value)))
{
Console.WriteLine("Removing:");
Console.WriteLine(XDocument.Parse(node.OuterXml).ToString());
root.RemoveChild(node);
}
}
catch (Exception Ex)
{
Console.WriteLine("Exception, as expected");
}
Console.WriteLine();
Console.WriteLine(XDocument.Parse(root.OuterXml).ToString());
Console.ReadKey();
}
}
}
このコードをVisual Studio Express 2010で実行すると、予想どおり例外が発生しません。繰り返しながらリストから何かを削除しているので、1つ期待します。
私が取得するのは、最初の子ノードのみが削除されたリストです。
無効な操作の例外が発生しないのはなぜですか?
IDEOne.com の同等のコードでは、予想される例外が発生することに注意してください: http://ideone.com/qoRBbb
また、すべての LINQ ( .Cast().Where()
) を削除すると、同じ結果が得られます。1 つのノードのみが削除され、例外はありません。
VSExpress の設定に問題はありますか?
遅延実行が関係していることは知っていますが、ソース列挙 (子メモ) を反復するために where 句が反復されると予想されることに注意してください。これにより、期待している例外が発生します。
私の問題は、VSexpress では例外が発生しないが、IDEOne では発生することです (両方/すべてのケースで例外が発生するか、少なくともそうでない場合は正しい結果が期待されます)。
Wouter の回答から、例外を与えるのではなく、最初の子が削除されたときにイテレータを無効にしているようです。公式にそう言っているものはありますか?この動作は他の場合に予想されますか? 「サイレントだが致命的」という例外ではなく、サイレントにイテレータを無効にすることを呼びます。