【问题标题】:Should I refactor these nested foreach statements?我应该重构这些嵌套的 foreach 语句吗?
【发布时间】:2016-05-26 13:15:34
【问题描述】:

我有一些功能允许用户在多个目录中搜索某种类型的文件,然后只将这些文件的路径添加到listbox。现在它是通过一些嵌套的foreach 语句完成的。它将检索数十万个文件路径,所以我很好奇还有什么其他有效的方法可以解决这个问题?

另外,我知道将这么多项目添加到listbox 听起来很愚蠢。我只是在做我被告知要做的事情。我有一种感觉,将来它会被要求删除,但文件路径仍然必须存储在某个地方的列表中。

注意:我使用WindowsAPICodePack 来获得一个允许选择多个目录的对话框。

List<string> selectedDirectories = new List<string>();

/// <summary>
/// Adds the paths of the directories chosen by the user into a list
/// </summary>
public void AddFilesToList()
{
    selectedDirectories.Clear(); //make sure list is empty

    var dlg = new CommonOpenFileDialog();
    dlg.IsFolderPicker = true;
    dlg.AddToMostRecentlyUsedList = false;
    dlg.AllowNonFileSystemItems = false;
    dlg.EnsureFileExists = true;
    dlg.EnsurePathExists = true;
    dlg.EnsureReadOnly = false;
    dlg.EnsureValidNames = true;
    dlg.Multiselect = true;
    dlg.ShowPlacesList = true;

    if (dlg.ShowDialog() == CommonFileDialogResult.Ok)
    {
        selectedDirectories = dlg.FileNames.ToList(); //add paths of selected directories to list
    }
}

/// <summary>
/// Populates a listbox with all the filepaths of the selected type of file the user has chosen
/// </summary>
public void PopulateListBox()
{
    foreach (string directoryPath in selectedDirectories) //for each directory in list
    {
        foreach (string ext in (dynamic)ImageCB.SelectedValue) //for each file type selected in dropdown
        {
            foreach (string imagePath in Directory.GetFiles(directoryPath, ext, SearchOption.AllDirectories)) //for each file in specified directory w/ specified format(s)
            {
                ListBox1.Items.Add(imagePath); //add file path to listbox
            }
        }
    }
}

编辑:不确定是否有区别,但我使用的是WPF listbox,而不是winforms

【问题讨论】:

  • 一句话...Linq
  • .. 你要在列表框中添加“数十万个文件路径”吗?
  • 是的,到目前为止,这就是我这样做的人想要的。将来它们可能不会显示在列表框中,但仍必须保存在某个列表中。
  • @DavidPine 之前没怎么用过 Linq,我会读一读。我确实在某处读到,它在引擎盖下执行与 foreach 循环相同的基本操作。

标签: c# wpf foreach nested-loops


【解决方案1】:

在学习 Linq 之外开始重构的一种方法是使用 AddRange 方法。关于它相对于 for 循环的性能优势的一个很好的解释: https://stackoverflow.com/a/9836512/4846465

然而,这个问题可能没有一个答案。

foreach (var directoryPath in selectedDirectories) 
{
    foreach (string ext in (dynamic)ImageCB) 
    {
        ListBox1.Items.AddRange(Directory.GetFiles(directoryPath, ext, SearchOption.AllDirectories).ToArray());
    }
}

【讨论】:

  • 好主意,但我使用的是 WPF 的列表框,它没有 AddRange 属性。
  • 也许对上面的代码 sn-p 稍作改动会将 Directory.GetFiles 的结果添加到本地 List 然后将该 List 设置为最外层 for 循环之外的 ListBoxs.ItemsSource .祝你好运,我对 WPF 知之甚少。
  • 嗯,是的,这是个好主意。我将对此与其他一些方法进行一些性能测试。最好的办法可能是创建一个视图模型来存储数据并将listbox 绑定到该模型,但不幸的是,该程序的其余部分不是这样编写的。
【解决方案2】:

你可以重构它,也可以让它保持原样。

如果你重构它;

您的代码将更具可读性、可理解性和可重用性。 您只需要编写几个方法。

您的方法可以用于其他事情,例如您当前的方法。

并且有效。

如果你让它保持原样;

您的代码有效。但很难理解和阅读。在出现错误的情况下很难调试。 但有效。

【讨论】:

  • 为什么代码“难以理解和阅读”和“难以调试”?
  • 这段代码可读性很强,但是使用 LINQ,你可以用更少的代码更有效地做到这一点
  • 这段代码包含多个嵌套的foreach,但如果将foreach拆分成方法,阅读起来会更方便。并且在调试时,您可以轻松了解问题所在。
猜你喜欢
  • 2020-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多