【问题标题】:I want to check the Count of an IEnumerable but it's very inefficient我想检查 IEnumerable 的计数,但效率很低
【发布时间】:2010-07-07 03:46:28
【问题描述】:

特别感谢 Rex M for this bit of wisdom:

    public IEnumerable<Friend> FindFriends()
    {
        //Many thanks to Rex-M for his help with this one.
        //https://*.com/users/67/rex-m

        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
        });
    }

找到所有用户的朋友后,我需要在 WPF 表单上显示他们。我有一个问题,并非所有用户都有至少 5 个朋友,有些甚至没有朋友!这是我所拥有的:

    private void showUserFriends()
    {
        if (friendsList.ToList().Count > 0)
        {
            friend1.Source = new BitmapImage(new Uri(friendsList.ToList()[0].Photo));
            label11.Content = friendsList.ToList()[0].Name;

            friend2.Source = new BitmapImage(new Uri(friendsList.ToList()[1].Photo));
            label12.Content = friendsList.ToList()[1].Name;

            //And so on, two more times. I want to show 4 friends on the window.
        }            
    }

所以这个问题有两个部分:

  1. 您建议我如何处理用户可能拥有的不同数量的朋友。使用我当前的代码,如果用户没有朋友,我会收到 IndexOutOfBounds 异常,因为 FriendsList[0] 不存在。

  2. 如何更有效地验证用户是否有朋友?调用 .ToList() 似乎很费力。

【问题讨论】:

    标签: c# .net linq ienumerable


    【解决方案1】:

    1) 将好友列表数据绑定到ListBox。您可以使用数据模板来显示图像和标签。

    2) 致电Any()

    【讨论】:

      【解决方案2】:

      在这种情况下,只需在 if 语句之前调用一次ToList(),而不是每次都创建一个列表。

      编辑

      您可能希望查看 MVVM 模式并让 XAML 将控件绑定到数据

      【讨论】:

      • 这是一个很好的局部优化。但是,甚至不需要转换为列表,因为 OP 已经有一个 IEnumerable,可以使用 foreach 对其进行迭代。
      • 虽然看起来他已经静态地创建了friend1、friend2等,这在使用foreach时可能会变得很困难,因为必须对您正在查看的索引进行额外的条件检查。我的第一个建议是将更改量保留为简单的重构
      【解决方案3】:

      当您在 IEnumerable 上调用 ToList() 时,您正在做的是枚举可枚举列表的所有元素并将结果放入容器中。因此,“代码气味”是在同一个 IEnumerable 上多次调用 ToList() 的代码,它应该只执行一次并保存到变量中。

      有一个简单的经验法则。如果您在整个 IEnumerable 列表(Linq 表达式)上进行操作,或者只是从头到尾导航列表,则使用 IEnumerable,如果您需要按索引访问列表,或者计算元素数量或通过list,先创建一个List容器并使用。

      List<Friend> friends = FindFriends().ToList();
      //Then use the friends list....
      

      现在,关于您的列表中是否有任何内容,正如这里的几个人所提到的,您可以使用数据绑定和像 ItemsControl 这样的控件,但如果您确实想动态构建 UI 内容,请使用循环,不要索引到数组中。

      List<Friend> friends = FindFriends().ToList();
      if(friends.Count > 0)
      {
        foreach(Friend f in friends)
        {
          //Create your Control(s) and add them to your form or panel's controls container
          // somthing like (untested) myPanel.Controls.Add(new Label(){Text = f.Name});
        }
      }
      

      【讨论】:

        【解决方案4】:

        使用某种 ItemContainer 控件,例如任何ItemsControl。您只需为项目的外观指定一个模板,并设置其ItemsSource 属性:

        myItemsControl.ItemsSource = new ObservableCollection(myFriends.Take(4));
        

        这将显示最多 4 个朋友,根据需要重复模板多次,但如果集合为空,则最少为 0。

        【讨论】:

          最近更新 更多