为啥我在 IDisposable 类中获得带有私有成员 IDisposable 的 CA2000?

Posted

技术标签:

【中文标题】为啥我在 IDisposable 类中获得带有私有成员 IDisposable 的 CA2000?【英文标题】:Why am I getting CA2000 with a private member IDisposable inside my IDisposable class?为什么我在 IDisposable 类中获得带有私有成员 IDisposable 的 CA2000? 【发布时间】:2011-01-11 23:04:56 【问题描述】:

我有一个实现 IDisposable 的类,因为它有一个 IDisposable 的私有成员字段“foo”(在构造函数中初始化)。我意外地收到 CA2000 代码分析错误,它希望我一定要处理掉 foo。但是,我在班级的 Dispose() 代码中有 foo.Dispose(),它应该会处理这个问题。

我进行了一些搜索,但令人惊讶的是找不到答案。我究竟做错了什么?显然我错过了一些基本的东西。我该如何编写代码来克服这个问题?

我的 VB 代码:

Public Class Bar
    Implements IDisposable

    Private Foo As SomeDisposableThing

    Public Sub New()
        Foo = New SomeDisposableThing() With .name = "hello"
    End Sub

    '''' snip ''''

    Private disposedValue As Boolean = False        ' To detect redundant calls '

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                If Foo IsNot Nothing Then Foo.Dispose()
            End If
        End If
        Me.disposedValue = True
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

End Class

【问题讨论】:

【参考方案1】:

CA2000 错误不是指实现IDisposable 的容器,而是指使用未正确处理的本地。原因是您在一次性对象上使用了对象初始化程序。将生成的实际代码基本上如下

Dim temp = New SomethingDisposable()
temp.Name = "hello"
Foo = temp

此代码被 FxCop 正确标记为在所有情况下都没有正确处理 IDisposabletemp.Name = "hello" 行可能会发生异常,在这种情况下不会处理)。

解决方法是这里不使用对象初始化器,直接初始化Foo

Foo = New SomethingDisposable()
Foo.Name = "hello"

【讨论】:

呸。消息:不要使用属性:( @Hans,我认为即使它是一个字段,它也会有相同的行为。任何行都可能引发异常(例如ThreadAbort),所以我猜测 FxCop 会在这里对字段和属性发出同样的警告。不过,还没有测试过这个理论。 @Hans,很有趣。我猜它只会将方法/道具调用标记为危险。 真糟糕! “With”初始化程序应该将其抽象出来。我不必知道“With”初始化程序使用临时变量!

以上是关于为啥我在 IDisposable 类中获得带有私有成员 IDisposable 的 CA2000?的主要内容,如果未能解决你的问题,请参考以下文章

C ++:如何在派生类中定义基类构造函数,如果基构造函数具有带有私有成员的初始化列表[重复]

为啥是 IDisposable 接口? [复制]

为啥 Enumerable.Range 实现 IDisposable?

为啥 FxCop 坚持使用 IDisposable 作为结构

为啥 IDisposable 具有 [ComVisible(true)] 属性?

如何访问其子类中的类的私有变量?