【问题标题】:How to return IEnumerable object in try catch block?如何在 try catch 块中返回 IEnumerable 对象?
【发布时间】:2020-11-27 23:22:01
【问题描述】:

我有一个方法可以从目录中读取所有文件作为字符串,然后遍历这些文件以获取文件内容以及其他详细信息,并从中返回 IEnumerable<DataFiles> 对象,如下所示:

public IEnumerable<DataFiles> GetFiles(string path)
{
    var listOfFiles = new List<string>();
    try
    {
        var jsonDataFiles = Directory.GetFiles(path, "*.json", SearchOption.AllDirectories);
        var textDataFiles = Directory.GetFiles(path, "*.txt", SearchOption.AllDirectories);
        listOfFiles.AddRange(jsonDataFiles);
        listOfFiles.AddRange(textDataFiles);
        for (int i = 0; i < listOfFiles.Count; i++)
        {
            var cfgPath = listOfFiles[i];
            if (!File.Exists(cfgPath)) { continue; }
            var fileContent = File.ReadAllText(cfgPath);
            var pieces = cfgPath.Split(System.IO.Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries);
            var fileName = pieces[pieces.Length - 1];
            var md5HashValue = GetMD5Hash(cfgPath);
            // error on below line
            yield return new DataFiles
            {
                FileName = fileName,
                FileContent = fileContent,
                MD5Hash = md5HashValue
            };
        }
    }
    catch (UnauthorizedAccessException ex)
    {
        // log error here
    }
    // error on below line
    return null;
}

但不知何故,我在上述方法中的yield return new 行和return null 行出现编译错误。以下是我看到的错误:

Cannot yield a value in the body of a try block with a catch clause
Cannot return a value from an iterator. Use the yield return statement to return a value, or yield break to end the iteration.

如果上面的代码抛出异常,那么我想返回空的 IEnumerable&lt;DataFiles&gt; 对象,否则它应该返回正确的 IEnumerable&lt;DataFiles&gt; 对象`,其中包含数据。

我在这里做错了什么?有没有更好更干净的方法来编写上述方法,这样我就不必在方法结束时返回 null?

【问题讨论】:

  • 如果你使用yield,你应该可以省略return null;这一行。否则您是否根据错误消息尝试过yield break
  • 但是如果抛出异常会发生什么?
  • 你的迭代将停止......这是你想要的吗?
  • 我更新了我的问题。我忘了添加那个细节。如果基本上抛出异常,我想返回空的IEnumerable&lt;DataFiles&gt; 对象,否则返回正确的IEnumerable&lt;DataFiles&gt; 具有完整内容的对象。
  • 那么不要使用yield,因为此时在计算枚举数之前不会抛出错误。我建议建立一个List&lt;DataFile&gt; 并返回它或null。它的使用 yield 在这里让你感到困惑。

标签: c# asp.net-core ienumerable


【解决方案1】:

执行以下步骤:

  • 在 try 块之外为 DataFiles 声明类型变量
  • 将数据分配给该变量:
yourDataFilesObj = new DataFiles
                {
                   FileName = fileName,
                   FileContent = fileContent,
                   MD5Hash = md5HashValue
                };

  • 外部 Catch 块写入为
yield return yourDataFilesObj;

【讨论】:

    【解决方案2】:

    正如 Jamiec 所提到的,您应该能够省略“return null” 未经授权的异常通常是文件系统错误,因此请事先获取所有文件。 还有第二个 try catch 块,以防您的处理出错

    public IEnumerable<DataFiles> GetFiles(string path)
        {
            var listOfFiles = new List<string>();
            try
            {
                listOfFiles.AddRange(System.IO.Directory.GetFiles(path, "*.json", System.IO.SearchOption.AllDirectories));
                listOfFiles.AddRange(System.IO.Directory.GetFiles(path, "*.txt", System.IO.SearchOption.AllDirectories));
            }
            catch (UnauthorizedAccessException ex)
            {
                // log error here
            }
            string fileName, fileContent;
            int md5HashValue; // im assuming this is an it, not sure
            //byte[] md5HashValue; // not sure
            for (int i = 0; i < listOfFiles.Count; i++)
            {
                try
                {
                    var cfgPath = listOfFiles[i];
                    if (!System.IO.File.Exists(cfgPath)) { continue; }
                    fileContent = System.IO.File.ReadAllText(cfgPath);
                    var pieces = cfgPath.Split(System.IO.Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries);
                    fileName = pieces[pieces.Length - 1];
                    md5HashValue = GetMD5Hash(cfgPath);
                }
                catch (Exception ex)
                {
                    // log other error here
                    continue;
                }
                // error on below line
                yield return new DataFiles
                {
                    FileName = fileName,
                    FileContent = fileContent,
                    MD5Hash = md5HashValue
                };
            }
        
        }
    

    【讨论】:

    • 感谢您的建议。这是编写上述方法的干净方法吗?只是确保
    • 至于清洁我不能说,只是我喜欢的风格。此外,我通常不会编写 yield 语句,所以它可能无法开箱即用。
    • 至于所有额外的 System.IO。和命名空间。我劫持了我正在处理的文件之一,并且不想改变那么多。你可以删除它们,因为我猜你已经包含了这些。
    • 现在知道了。我用我只使用 List 的新代码更新了我的问题,但是当我返回它时,我在最后将它标记为ReadOnly。你认为这也能毫无问题地工作吗?最后返回的我的列表是IEnumerable,但只读对吗?
    • 我认为这会很好地工作(但通常大约 30% 的假设会在几年后咬住我)我从未使用过只读的,我认为这会发生。之后我会写一个测试来仔细检查,或者找到一些不错的 m-soft 文档。
    猜你喜欢
    • 1970-01-01
    • 2012-05-18
    • 1970-01-01
    • 2016-05-06
    • 1970-01-01
    • 2019-08-31
    • 2015-07-07
    • 1970-01-01
    • 2021-12-25
    相关资源
    最近更新 更多