使using语句可用于多个一次性物品 [英] Make using statement usable for multiple disposable objects

查看:114
本文介绍了使using语句可用于多个一次性物品的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在文件夹中有一堆文本文件,并且所有文件都应具有相同的标题。换句话说,所有文件的前100行应相同。所以我写了一个函数来检查这种情况:

I have a bunch of text files in a folder, and all of them should have identical headers. In other words the first 100 lines of all files should be identical. So I wrote a function to check this condition:

private static bool CheckHeaders(string folderPath, int headersCount)
{
    var enumerators = Directory.EnumerateFiles(folderPath)
        .Select(f => File.ReadLines(f).GetEnumerator())
        .ToArray();
    //using (enumerators)
    //{
        for (int i = 0; i < headersCount; i++)
        {
            foreach (var e in enumerators)
            {
                if (!e.MoveNext()) return false;
            }
            var values = enumerators.Select(e => e.Current);
            if (values.Distinct().Count() > 1) return false;
        }
        return true;
    //}
}

我使用枚举器的原因是内存效率。而不是将所有文件内容加载到内存中,我逐行并发地枚举文件,直到发现不匹配或已检查所有标头为止。

The reason I am using enumerators is memory efficiency. Instead of loading all file contents in memory I enumerate the files concurrently line-by-line until a mismatch is found, or all headers have been examined.

我的问题很明显通过注释的代码行。我想使用 using 块可以安全地处置所有枚举器,但是不幸的是, using(枚举器)不能编译。显然,使用只能处理单个一次性对象。我知道我可以通过将整个内容包装在 try-finally 块中,并最终在循环内部运行处理逻辑来手动处理枚举数,但似乎很尴尬。在这种情况下,有什么机制可以使 using 语句成为可行的选择?

My problem is evident by the commented lines of code. I would like to utilize a using block to safely dispose all the enumerators, but unfortunately using (enumerators) doesn't compile. Apparently using can handle only a single disposable object. I know that I can dispose the enumerators manually, by wrapping the whole thing in a try-finally block, and running the disposing logic in a loop inside finally, but is seems awkward. Is there any mechanism I could employ to make the using statement a viable option in this case?

更新

我刚刚意识到我的功能存在严重缺陷。枚举器的构造不可靠。一个已锁定的文件可能会导致异常,尽管已经创建了一些枚举器。这些枚举器将不会被处置。这是我要修复的问题。我正在考虑这样的事情:

I just realized that my function has a serious flaw. The construction of the enumerators is not robust. A locked file can cause an exception, while some enumerators have already been created. These enumerators will not be disposed. This is something I want to fix. I am thinking about something like this:

var enumerators = Directory.EnumerateFiles(folderPath)
    .ToDisposables(f => File.ReadLines(f).GetEnumerator());

扩展方法 ToDisposables 应该确保

推荐答案

您可以在上创建一个一次性包装纸枚举器

class DisposableEnumerable : IDisposable
{
    private IEnumerable<IDisposable> items;

    public event UnhandledExceptionEventHandler DisposalFailed;

    public DisposableEnumerable(IEnumerable<IDisposable> items) => this.items = items;

    public void Dispose()
    {
        foreach (var item in items)
        {
            try
            {
                item.Dispose();
            }
            catch (Exception e)
            {
                var tmp = DisposalFailed;
                tmp?.Invoke(this, new UnhandledExceptionEventArgs(e, false));
            }
        }
    }
}

使用它对您的代码产生最小的影响:

and use it with the lowest impact to your code:

private static bool CheckHeaders(string folderPath, int headersCount)
{
    var enumerators = Directory.EnumerateFiles(folderPath)
        .Select(f => File.ReadLines(f).GetEnumerator())
        .ToArray();

    using (var disposable = new DisposableEnumerable(enumerators))
    {
        for (int i = 0; i < headersCount; i++)
        {
            foreach (var e in enumerators)
            {
                if (!e.MoveNext()) return false;
            }
            var values = enumerators.Select(e => e.Current);
            if (values.Distinct().Count() > 1) return false;
        }
        return true;
    }
}

问题是您必须分别处理这些对象反正一个。但这取决于您在哪里封装该逻辑。而且我建议的代码没有手动最终尝试 ,)

The thing is you have to dispose those objects separately one by one anyway. But it's up to you where to encapsulate that logic. And the code I've suggested has no manual try-finally,)

这篇关于使using语句可用于多个一次性物品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆