【问题标题】:Convert IEnumerable to List to comply with method signature [closed]将 IEnumerable 转换为 List 以符合方法签名 [关闭]
【发布时间】:2020-12-22 02:04:42
【问题描述】:

我有一个下面的代码,它返回所有文件的列表。它正在从文件夹和子文件夹中读取所有文件并将其作为列表返回给用户。

我在下面的代码中有两种情况。

案例1:

  • 如果IS_PROC 为真,那么我会以不同的方式获取files,然后将其返回给用户。
  • 在这种情况下,我有一个IEnumerable 查询,我将其转换回列表,因为我的方法签名是IList。不确定将IEnumerable 转换为List 是否是个好主意。

案例2:

  • 如果IS_PROC 为假,我会以另一种方式获取files,然后将其返回给用户。
  • 在这种情况下,我只有一个列表,所以我将其返回。

下面是我的代码:

private IList<string> ReadFiles(string path)
{
    var files = new List<string>();
    try
    {
        if (IS_PROC)
        {
            // case 1:
            IEnumerable<string> query =
                from directory in System.IO.Directory.EnumerateDirectories(path)
                let dev = System.IO.Path.Combine(directory, "dev")
                from file in System.IO.Directory.EnumerateFiles(directory)
                let fi = new System.IO.FileInfo(file)
                let dev_file = System.IO.Path.Combine(dev, fi.Name)
                select System.IO.File.Exists(dev_file) ? dev_file : file;
            // is this the right way to do it?
            return (!query.Any()) ? files : query.ToList();
        }
        // case 2:
        var lclJsonFiles = Directory.GetFiles(path, "*.json", SearchOption.AllDirectories);
        var lclTxtFiles = Directory.GetFiles(path, "*.txt", SearchOption.AllDirectories);
        files.AddRange(lclJsonFiles);
        files.AddRange(lclJsonFiles);
    }
    catch (Exception ex)
    {
        // log error here
    }
    return files;
}

所以我的问题是-

  • 考虑到我在这两种情况下的操作,从我的方法中返回 IList 是否有意义?
  • 我的一个案例返回IEnumerable,其他案例返回List,为了使其与我的方法签名兼容,我将IEnumerable 转换为Case1 中的列表?这是将IEnumerable 转换为List 的正确方法吗?
  • 上面的方法有没有更好的写法?

【问题讨论】:

  • 如果您在案例 1 中不执行 .ToList();,则不会枚举查询,因此评估将由调用者完成(以及调用者代码中引发的异常)。但是case1和2是完全不同的,你应该使用两个不同的方法
  • 是的,即使我执行两个单独的方法,一个会返回 IEnumerable,另一个会返回 IList,所以在调用方我期待列表,那么我应该更改调用方以期待 IEnumerable 吗?
  • 如果你想返回一个IEnumerable&lt;string&gt;,那么你可以return query;在case 1和return Directory.EnumerateFiles(path, "*.json", SearchOption.AllDirectories).Union(Directory.EnumerateFiles(path, "*.txt", SearchOption.AllDirectories));在case 2。但正如 Camilo 所指出的,IEnumerable 的行为与List 不同:在访问集合之前不会进行评估(当您调用.ToList() 时会发生这种情况),这将发生在调用方。
  • 我明白了,如果我想在 case1 中返回 IList,那么我所做的是对的吗? return (!query.Any()) ? files : query.ToList();
  • 为什么不总是返回query.ToList()files 那时也是一个空列表。

标签: c# list ienumerable


【解决方案1】:

你可以用任何一种方式编写方法,这真的取决于你想做什么。如果你想返回一个IEnumerable,你可以放弃ToList() 调用,它应该可以工作。您也可以将GetFiles 替换为Directory.EnumerateFiles,因为它还会返回IEnumerable

private IEnumerable<string> ReadFiles(string path)
{
    try
    {
        return IS_PROC
            ? (from directory in Directory.EnumerateDirectories(path)
                let dev = Path.Combine(directory, "dev")
                from file in Directory.EnumerateFiles(directory)
                let fi = new FileInfo(file)
                let devFile = Path.Combine(dev, fi.Name)
                select File.Exists(devFile) ? devFile : file)
            : Directory
                .EnumerateFiles(path, "*.json", SearchOption.AllDirectories)
                .Union(Directory.EnumerateFiles(path, "*.txt", SearchOption.AllDirectories));
    }
    catch (Exception ex)
    {
        // log error here
        return new List<string>();
    }
}

否则,您可以将.ToList() 添加到返回值的末尾并返回IList。请注意,List 实现了 IEnumerable,因此无论哪种情况,您都可以只返回一个 List

【讨论】:

  • 我看到这看起来很干净。所以如果我决定在最后添加.ToList(),那么当它在这两种情况下都找不到任何文件时会发生什么 - 它会在空对象上引发调用.ToList() 的异常吗?
  • 您指的是什么null 对象?我不相信这些陈述中的任何一个都会返回null,对吗?另外,在您的原始代码中,您在query 上调用.Any,如果querynull,则会抛出,所以我认为您不必担心!
  • 这里的catch 最终大部分无用(除了对EnumerateDirectories 的初始检查),给人一种错误的印象,即IO 错误会被捕获。我会完全摆脱 try-catch,所以很明显调用者必须处理异常
  • 好点 - 他们可以进行日志记录,然后throw
  • @cs98 如果查询没有返回任何元素,或者换句话说,如果.Any() == false,那么.ToList() 将只返回一个空列表(因为没有什么可以添加到其中)
猜你喜欢
  • 2012-02-24
  • 2018-08-04
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 1970-01-01
相关资源
最近更新 更多