将IDisposable作为参数传递



将IDisposable作为参数传递给方法并在该方法中处理它是一种好做法吗?当您必须使用多个线程时,这是不可避免的。嗯,最佳实践是所有者(调用者)应该处理它。

public void MyMethod(MyClass reader){
    using(reader){
        //some code
    }
}

如果所有者(创建线程)不再存在怎么办?例如

interface IReader : IDisposable {
    string Read();
}
public class MyReader : IReader {
    public string Read()
    {
        return "hellow world";
    }
    public void Dispose()
    {
        //dispose code
    }
}

问题就出在这里了

public void Start() {
    MyReader[] readerSet = new MyReader[5];
    for (int i = 0; i < readerSet.Length; i++) {
        readerSet[i] = new MyReader();
    }
    foreach (IReader reader in readerSet) {
        ThreadPool.QueueUserWorkItem(new WaitCallback(Run), reader);
    }
    //exit after creating threads
}

public void Run(Object objReader) {
    IReader reader = (IReader)objReader;
    using (reader) { 
    //use the reader
    }
}

我认为你最好使用一个创建委托来保证对象的处理。

public void Start() {
    var makeReader = new Func<IReader>(() => new MyReader()); 
    for (int i = 0; i < 5; i++) {
        ThreadPool.QueueUserWorkItem(Run, makeReader);
    }
}    
public void Run(Object state) {
    var makeReader = (Func<IReader>)state;
    using (var reader = makeReader()) { 
        //use the reader
    }
}

不可以,应该由业主处理。所有者通常是首先创建IDisposable实例的对象。你可以在这里阅读关于idisable的最佳实践。

执行传递式处置类型中定义的所有可处置字段从你的Dispose方法。您应该对任何字段调用Dispose()对象控制其生命周期。例如,考虑一个案例你的对象拥有一个私有TextReader字段。在你的类型处置,你应该调用TextReader对象的处置然后处置它的可处置字段(流和编码,for例),等等。如果在Dispose(bool Dispose)中实现方法,只有在处理参数为时才会发生期间不允许真实触摸其他托管对象终结。另外,如果你的对象不拥有给定的一次性物品,就不应该像其他物品一样试图丢弃它代码仍然可以依赖于它处于活动状态。这两个都可能导致subtle-to-detect bug。

尽量减少传递IDisposable实例可能是一个好主意,这样您就不必过多地考虑所有者。

这完全取决于你的具体情况。

一般来说,"所有者"应该处理对象,但你的工作是找出谁是谁。它可能不是创建者,也可能不是调用者

从创建到Dispose调用的任何时刻,IDisposable的任何实例都应该有一个负责删除它的所有者。通常,IDisposable的所有者将是创建它的实体,但在某些情况下,让对象将IDisposable的所有权移交给另一个对象可能会有所帮助。例如,考虑以下两个假设的类:

  1. SoundSource,它实现了一个GetAudio方法,返回声音的下一个"n"样本。SoundSource实现了IDisposable,因为它可以用于从文件流式传输音频;如果处理不当,文件将无法关闭。AsyncSoundPlayer,它实现了一个PlaySound方法,该方法接受一个SoundSource并开始播放,放弃之前播放的任何声音。

在许多情况下,加载SoundSource的例程不会真正关心它何时完成播放;让播放例程拥有SoundSource的所有权会更方便。请注意,在某些情况下,请求播放的例程可能希望保留SoundSource的所有权。最好的方法是允许一种方法,通过这种方法,例程的调用者可以指定它是希望保留还是移交传入的IDisposable的所有权。

相关内容

  • 没有找到相关文章