对于这种简单的Linq用法,我的代码效率很低

时间:2010-07-07 03:03:29

标签: c# .net linq linq-to-xml

我有以下方法可以解析XML响应中的信息并返回一组用户。

我选择创建一个Friend类并将List<Friend>返回给调用方法。

这是我到目前为止所做的,但我注意到ids.ToList()。Count方法将每个id元素解析为List,然后在for条件中再次执行。这只是非常无效。

public List<Friend> FindFriends()
{
    List<Friend> friendList = new List<Friend>();

    var friends = doc.Element("ipb").Element("profile").Element("friends").Elements("user");
    var ids = from fr in friends
              select fr.Element("id").Value;

    var names = from fr in friends
                select fr.Element("name").Value;

    var urls = from fr in friends
                select fr.Element("url").Value;

    var photos = from fr in friends
                select fr.Element("photo").Value;

    if (ids.ToList().Count > 0)
    {
        for (int i = 0; i < ids.ToList().Count; i++)
        {
            Friend buddy = new Friend();
            buddy.ID = ids.ToList()[i];
            buddy.Name = names.ToList()[i];
            buddy.URL = urls.ToList()[i];
            buddy.Photo = photos.ToList()[i];

            friendList.Add(buddy);
        }
    }            

    return friendList;
}

2 个答案:

答案 0 :(得分:10)

第一个问题 - 您必须返回List<Friend>吗?你能回来IEnumerable<Friend>吗?如果是这样,性能会好很多:

IEnumerable<Friend> FindFriends()
{
    return doc.Descendants("user").Select(user => new Friend {
        ID = user.Element("id").Value,
        Name = user.Element("name").Value,
        Url = user.Element("url").Value,
        Photo = user.Element("photo").Value
    });
}

不是实际创建新的存储桶并将值填充到它们中,而是创建投影,或者只包含如何创建的所有逻辑的新对象没有实际创建它们的新朋友对象。当调用者最终通过IEnumerable开始foreach时,它们就会被创建。这称为“延期执行”。

这也是一个假设 - XML片段中的所有<user>节点都是朋友。如果不是这样,那么XML选择的第一部分可能需要是 little 更复杂。

正如@anon指出的那样,即使您确实需要返回List<Friend>由于某些原因而从您提供的信息中显而易见,您也可以在结束时拨打.ToList()退货声明。这将直接将我上面描述的投影直接执行到新的存储桶中,因此您只需创建一个。

答案 1 :(得分:0)

为什么需要单独的ids / names / urls / photos变量?结合一切。如果您不需要List,则可以取消ToList()调用。

List<Friend> friendList = (from f in doc.Element("ipb").Element("profile").Element("friends").Elements("user")
                          select new Friend() { 
                                                 ID = f.Element("id").Value, 
                                                 Name = f.Element("name").Value,
                                                 URL = f.Element("url").Value,
                                                 Photo = f.Element("photo").Value
                                 }).ToList();

return friendList;