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

Ser*_*pia 1 .net c# 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;
}
Run Code Online (Sandbox Code Playgroud)

Rex*_*x M 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
    });
}
Run Code Online (Sandbox Code Playgroud)

这不是实际创建新桶和将值填充到它们中,而是创建一个投影或一个新对象,它只包含如何创建新的Friend对象而不实际创建它们的所有逻辑.当调用者最终开始foreach超过IEnumerable 时,它们就会被创建.这称为"延迟执行".

这也是一个假设 - <user>XML片段中的所有节点都是朋友.如果事实并非如此,在XML选择的第一部分可能需要一点点更复杂.

正如@anon指出的那样,即使你确实需要List<Friend>从你提供的信息中找出一些不明显的原因,你也可以.ToList()在return语句的末尾调用.这将直接将我上面描述的投影直接执行到新的存储桶中,因此您只需创建一个.

  • 我不必返回List,我只是习惯使用它.我似乎总是忘记IEnumarable.谢谢,这段代码真是太好了.我会测试一下,看看它是否有效.再次感谢! (2认同)