Coverity、Enumerable.Where(this ...) 和 IDisposable

发布于 2024-12-19 08:38:32 字数 848 浏览 0 评论 0原文

因此,代码分析告诉我 Enumarble.Where(this ...) 正在返回 WhereListIterator 的实例,它(看起来是)内部类型在实现 IDisposable 的 .NET 框架内。

Coverity 不喜欢 IDisposable 未被处置,因此建议我处置所述实例。显然,如果不进行一些类型检查,我就无法处置该实例,因为 Enumerable.Where(this ...) 据说返回 IEnumerable,这确实不是来自 IDisposable 的 ihnerit。

我的问题是:.NET 是否期望我处理 WhereListIterator,或者迭代器自行处理(例如,在每次枚举之后)。如果我不希望处置它,那么为什么要实现该接口?这引出了第三个稍微不相关的问题:如果显式实现了 IDisposable,Coverity(代码分析)是否仍然认为我应该处置它?

代码示例:

var myList = new List<int>{ 1, 2, 3, 4 };

var evenNumbers = myList.Where(x => x % 2 == 0);

foreach(var number in evenNumbers)
{
    Console.WriteLine(number);
}

if(evenNumbers is IDisposable)
{
    ((IDisposable)evenNumbers).Dispose(); // This line will be executed
}

So code analysis is telling me that Enumarble.Where(this ...) is returning an instance of WhereListIterator<T>, which is (looks to be) an internal type within the .NET framework that implements IDisposable.

Coverity doesn't like IDisposable's to go un-disposed, and is therefore suggesting I dispose of said instance. Obviously I can't dispose of the instance without doing some type checking, as Enumerable.Where(this ...) is said to return IEnumerable<T>, which does not ihnerit from IDisposable.

My question is this: Does .NET expect me to dispose of the WhereListIterator<T>, or does the iterator dispose of itself (say, after each enumeration). If I'm not expected to dispose of it, then why is the interface implemented? This leads me to a third, slightly unrelated question: If IDisposable was implemented explicitly, would Coverity (code analysis) still think that I should dispose of it?

Code Example:

var myList = new List<int>{ 1, 2, 3, 4 };

var evenNumbers = myList.Where(x => x % 2 == 0);

foreach(var number in evenNumbers)
{
    Console.WriteLine(number);
}

if(evenNumbers is IDisposable)
{
    ((IDisposable)evenNumbers).Dispose(); // This line will be executed
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉栀 2024-12-26 08:38:32

不,您不需要自己处理它。请注意,您无需使用 LINQ 即可演示此类事情。在这种情况下,我相信 WhereListIterator 实际上是一个手写的类,但迭代器块显示了类似的东西:

using System;
using System.Collections.Generic;

public class Program
{
    static void Main(string[] args)
    {
        var empty = Empty();
        Console.WriteLine(empty is IDisposable); // Prints True
    }

    static IEnumerable<string> Empty()
    {
        yield break;
    }
}

它确实实现了 IDisposable 因为它不仅实现了 IEnumerable 而且 IEnumerator 作为一种优化 - 可迭代也充当迭代器,在常见情况下,您只需要迭代一次。 foreach 循环将隐式处置 IEnumerator,除非您进行迭代,否则您不需要处置它。

基本上,你在这里没问题 - 尽管遗憾的是 Coverity 正在警告你这一点。 (老实说,我自己没有使用过 Coverity - 我不知道是否可以做一些事情来调整它的行为。)

No, you don't need to dispose of it yourself. Note that you can demonstrate this sort of thing without any need for LINQ. In this case I believe WhereListIterator<T> is actually a hand-written class, but an iterator block shows something similar:

using System;
using System.Collections.Generic;

public class Program
{
    static void Main(string[] args)
    {
        var empty = Empty();
        Console.WriteLine(empty is IDisposable); // Prints True
    }

    static IEnumerable<string> Empty()
    {
        yield break;
    }
}

It really implements IDisposable because it implements not just IEnumerable<T> but also IEnumerator<T> as an optimization - the iterable acts as the iterator as well, in the common case where you only iterate once. A foreach loop will implicitly dispose of an IEnumerator<T>, and you don't need to dispose of it unless you iterate anyway.

Basically, you're fine here - although it's a pity that Coverity is warning you about it. (I haven't used Coverity myself, to be honest - I don't know if there's something you can do to tweak its behaviour here.)

紫轩蝶泪 2024-12-26 08:38:32

如果您不使用 foreach 循环并使用旧的迭代方式

var v = new List<int>() { 1,2,3};
var enumerator = v.GetEnumerator();
while (enumerator.MoveNext())
{

    Console.WriteLine(enumerator.Current);
}

,那么您应该调用 Dispose 方法

if you are not using the foreach loop and using the old way to iterate

var v = new List<int>() { 1,2,3};
var enumerator = v.GetEnumerator();
while (enumerator.MoveNext())
{

    Console.WriteLine(enumerator.Current);
}

then you should call the Dispose method

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文