如果在 using 语句中使用 IDisposable 字段,是否需要使当前类 IDisposable 可用?

Do you need to make your current class IDisposable if using an IDisposable field in a using statement?

提问人:sr28 提问时间:11/17/2023 更新时间:11/17/2023 访问量:67

问:

这是我的例子:

public sealed class BigLogicClass
{
    private SmallDisposableClass fMyDisposableClass;

    public void Setup(someParam)
    {
        var eventHandlerFactory = new EventHandlerFactory();
        var eventHandler = eventHandlerFactory.Create(someParam);
        eventHandler.SomeEvent += OnDoingThisEvent;
    }

    public void DoSomething()
    {
        using(fMyDisposableClass = new SmallDisposableClass())
        {
            // run a long process.
        }
    }

    private void OnDoingThisEvent()
    {
        fMyDisposableClass.RunSomething();
    }
}

我在这个类中有一个方法“OnDoingThisEvent”,它由另一个类“eventHandler”在其他地方调用。“OnDoingThisEvent”需要能够使用“fMyDisposableClass”。但是,这样做会引发代码分析错误,该错误基本上表明“fMyDisposableClass”未正确处置。

它唯一被实例化的地方是 ,它包含了 'fMyDisposableClass' 应该存在的进程的生命周期。在此过程中,可以调用“OnDoingThisEvent”。据推测,这意味着一旦该过程完成,“fMyDisposableClass”的实例将被处理掉。那么这是一个问题吗?如果是这样,我如何在不使“BigLogicClass”成为一次性使用然后实现处置的情况下使用“fMyDisposableClass”?using statement

C# IDISPOSABLE

评论

0赞 Ralf 11/17/2023
我不明白这如何确保事件处理程序在fMyDisposableClass不存在或被释放时不会触发该事件。Setup&DoSomething 应该只是一个浮出水面的方法,因此类用户不能在这里摸索并将事件附加/分离在 using 块中而不是其他地方。
1赞 Hans Passant 11/17/2023
保留对已释放对象的引用不是一个好主意,请确保可靠地生成 ObjectDisposedException。最好将对象作为方法参数传递。但是不,当 BigLogicClass 对象的生命周期到期时,它就死了,所以你不必让它更死。
0赞 sr28 11/17/2023
@HansPassant - 好吧,听起来虽然这并不理想,但它应该不会引起问题。fMyDisposableClass 应仅在进程的长度内生存。“OnDoingThisEvent”应该只能在该过程中调用,因此理论上,一旦释放了 fMyDisposableClass,就不应该尝试调用它。但是,添加 ObjectDisposedException 应该足够了。

答:

1赞 Dmitry Bychenko 11/17/2023 #1

在您当前的实现中(这是可疑的),没有必要将类声明为 ,因为类不拥有非托管资源。类方法分配释放一些资源,仅此而已:类本身并不拥有这些资源:IDisposable

    public void DoSomething()
    {
        // Some resources are allocated here...
        using(fMyDisposableClass = new SmallDisposableClass())
        {
            // run a long process.
        }
        // ...and releases here
    }

    private void OnDoingThisEvent()
    {
        // Note, that fMyDisposableClass can be disposed here
        // Any calls - RunSomething - are very suspicious.
        fMyDisposableClass.RunSomething();
    }

你,可能,像这样的东西:

public sealed class BigLogicClass
{
    // Instance doesn't own unmanaged resources   

    public void Setup(someParam)
    {
        var eventHandlerFactory = new EventHandlerFactory();
        var eventHandler = eventHandlerFactory.Create(someParam);
        eventHandler.SomeEvent += OnDoingThisEvent;
    }

    public void DoSomething()
    {
        using (var myDisposableClass = new SmallDisposableClass())
        {
            // run a long process.

            ...

            // Fire event using myDisposableClass which is not disposed yet 
            OnDoingThisEvent(myDisposableClass);  

            ... 
        }
    }

    private void OnDoingThisEvent(SmallDisposableClass myClass)
    {
        myClass.RunSomething();
    }
}

编辑:如果要触发事件

    ...
    private void OnDoingThisEvent(SmallDisposableClass myClass)
    {
        myClass.RunSomething();

        // Let user 
        EventHandler someEvent = SomeEvent;

        if (someEvent != null)
        { 
            someEvent(this, EventArgs.Empty);
        } 
    }

    public event EventHandler SomeEvent;
    ...

评论

0赞 Ralf 11/17/2023
eventHandler.SomeEvent += OnDoingThisEvent;eventHandler 如何知道它在调用方法时应该提供的 myClass?
0赞 Dmitry Bychenko 11/17/2023
@Ralf:如果你想触发一个事件,你可以用:请看我的编辑OnDoingThisEvent