我从Silverlight应用程序中获得了以下代码片段:

var messages = from message in XcurrentMsg.Descendants("message")
                               where    DateTime.Parse(message.Attribute("timestamp").Value).CompareTo(DateTime.Parse(MessageCache.Last_Cached())) > 0
                               select new
                               {
                                   ip = message.Attribute("ip").Value,
                                   timestamp = message.Attribute("timestamp").Value,
                                   text = message.Value,
                               };
                if (messages == null)
                    throw new SystemException("No new messages recorded. Application tried to access non existing resources!");

            foreach (var message in messages)
            {
                XElement temporaryElement = new XElement("message", message.text.ToString(), new XAttribute("ip", message.ip.ToString()), new XAttribute("timestamp", message.timestamp.ToString()));
                XcurrentMsg.Element("root").Element("messages").Add(temporaryElement);

                AddMessage(BuildMessage(message.ip, message.timestamp, message.text));
                msgCount++;
            }

            MessageCache.CacheXML(XcurrentMsg);
            MessageCache.Refresh();


XcurrentMsg是从服务器获取的XDocument,其中包含以下消息:
结构体

<root>
    <messages>
          <message ip="" timestamp=""> Text </message>
    </messages>
</root>


我想使所有“消息”都比上次缓存XcurrentMsg时更新。
只要我切出“ XElement临时元素”和“ XcurrentMsg.Element ....”,它就可以正常工作。
并简单地使用currentMsg字符串作为输出。
但是我想将“新消息”保存在XcurrentMsg / Cache中。
现在,如果我不删节,我的应用程序将变得非常疯狂。
我认为它会不停地将无限元素写入XcurrentMsg。

我不知道是什么问题。

问候,

最佳答案

这是经典的LINQ陷阱。

变量messages保存对IEnumerable<someAnonymousType>的引用。您所犯的错误是假定在为messages分配后,已枚举所有Descendents并且已构建someAnonymousType集。

实际上,这一刻什么也没发生。仅当您开始使用foreach枚举集合时,才会枚举Descendents并创建匿名类型。即使尚未列举整个Descendents集合,实际上直到第一个满足where子句条件的项目都被枚举,然后一次仅创建一个投影(select的结果),如下所示: foreach循环通过。

因此,您添加的消息也包含在枚举中,因为这会使其他消息陷入无限循环,或者至少出现错误,提示您尝试修改要枚举的集合。

如果要确定要枚举的项目列表,然后在向查询添加循环ToList()之前将其枚举固定,则将创建一个List<T>

var messages = (from message in XcurrentMsg.Descendants("message")
                           where    DateTime.Parse(message.Attribute("timestamp").Value).CompareTo(DateTime.Parse(MessageCache.Last_Cached())) > 0
                           select new
                           {
                               ip = message.Attribute("ip").Value,
                               timestamp = message.Attribute("timestamp").Value,
                               text = message.Value,
                           }).ToList();


请注意,无论哪种情况都不需要测试messages是否为null,它不会为null,它可能是空的枚举或列表。

关于c# - 操纵现有的XDocument(失败),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2856426/

10-09 08:14