使用ObjectDisposedException

时间:2016-11-28 07:05:02

标签: c#

实现Dispose模式时,对象的属性应在对象被处理后抛出ObjectDisposedException。

如果每个属性和方法在setter的开头有一行代码并且getter抛出该异常,即使它只是ThrowIfDisposed(),它看起来像很多重复的代码。如果您有40个属性,那么80条重复的行。在大型课程中,它可以非常快速地加起来。

我还没有找到更好的方式,所以它看起来就是这样,但我想我会问。还有更好的方法吗?

2 个答案:

答案 0 :(得分:7)

如果你在一个类中有40个属性,那么你可能有一个设计问题,但继续...这实际上取决于具体的用例,但是如果该属性实际上不能实际上你应该抛出ObjectDisposedException因为班级已被处理而得到解决。举一个具体的例子:

public class MyStream : IDisposable
{
    private string name;
    private Stream stream;

    public MyStream(string name)
    {
        this.Name = name;
        this.Stream = new FileStream(...);
    }

    public string Name
    {
        get
        {
            return this.name;
        }
    }

    public Stream Stream
    {
        get
        {
            if (this.IsDisposed)
            {
                throw new ObjectDisposedException();
            }

            return this.stream;
        }
    }

    private bool IsDisposed { get; set; }

    public void Dispose()
    {
        if (!this.IsDisposed)
        {
            this.IsDisposed = true;
            this.Stream.Dispose();
            this.Stream = null;
        }
    }
}

这里,属性Stream抛出异常,因为底层流已被丢弃,因此无法再使用它。但是Name没有理由抛出。 从那里开始,在许多情况下,您可以对代码进行分解,以便访问实际的有问题的属性会引发异常:

public int Length
{
    get 
    {
        // Since we access the Stream property, the ObjectDisposedException
        // will be thrown when the class is disposed
        return this.Stream.Length;
    }
}

如果在遵循此模式后仍有太多属性要装饰,则可以使用Fody之类的库来允许您在编译时注入行为。使用它,您可以根据需要创建应用于属性的属性[ThrowIfDisposed]

答案 1 :(得分:0)

检查其他主题:Handling ObjectDisposedException correctly in an IDisposable class hierarchy

每次有人访问实现:IDisposable的类的属性时,都不需要抛出异常。只有在访问必须处理的对象时才需要(例如,写入/读取文件,访问网络套接字,......)。对于所有其他情况,你可以选择正常的课程。

通常,对象/类没有大量的属性,因为可以选择将它们分成更多的类 - >这将允许您只制作此:IDisposable的一部分,其余的将独立于IDisposable类。