Si consideri il seguente codice:Linq, XmlNodes, foreach ed eccezioni
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();
}
}
}
Quando eseguo questo codice in Visual Studio Express 2010 non ottengo un'eccezione, come previsto. Mi aspetterei uno perché sto rimuovendo qualcosa da una lista mentre lo itera.
Quello che faccio ottenere un elenco indietro con solo il primo nodo figlio rimosso:
Perché non ottengo un'eccezione operazione non valida?
Nota che il codice equivilent in IDEOne.com dà l'eccezione prevista: http://ideone.com/qoRBbb
Si noti inoltre che se tolgo tutto il LINQ (.Cast().Where()
) ottengo lo stesso risultato, un solo nodo rimosso , nessuna eccezione.
C'è qualche problema con le mie impostazioni in VSExpress?
Nota che so esecuzione differita è coinvolto, ma mi aspetto la clausola where, quando iterato su di iterare sulla enumerazione sorgente (nota bambino), che darebbe l'eccezione mi aspetto.
Il mio problema è che non ottengo quell'eccezione in VSexpress, ma faccio in IDEOne (mi aspetterei che in entrambi/tutti i casi, o almeno in caso contrario, mi aspetterei il risultato corretto).
Da Wouter's answer sembra è invalidare l'iteratore, quando il primo figlio è stato rimosso, piuttosto che dare un'eccezione. C'è qualcosa di ufficiale che dice questo? Questo comportamento è previsto in altri casi? Chiamerei invalidare l'iteratore in silenzio piuttosto che con un'eccezione "Silenzioso ma mortale".
Non vedo l'output di 'Console.WriteLine (" Rimozione: ");' anche nel risultato. Sei sicuro che il loop si spenga? – Impworks
È in cima – IronMan84
Siamo spiacenti, lo screenshot modificato (aggiunto quel controllo/dimostrazione dopo il test iniziale) –