引用using()块之外的对象

Jam*_*ing 3 c# dispose idisposable using using-statement

关于这个主题有很多问题,但是我没有找到一个涵盖我特别需要理解的内容.

我的一位开发人员编写了这段代码:

//

    //  ValidationDataTable is a typed DataTable, generated by the Framework
    ValidationDataTable  validationTable;
    using (ValidationTableAdapter adapter = new ValidationTableAdapter ()) {
        using (validationTable = adapter.GetData()) { }
    }

    datafeedValidators.Add(new CountryFieldValidator(validationTable.ToDictionary(key => key.CountryCode, value => value.CountryName)));

    //  Party on...

//
Run Code Online (Sandbox Code Playgroud)

我的理解:本validationTable已被释放,但是当它在过去的代码生产线的引用不收集垃圾-但应该还是有抛出ObjectDisposedException.ToDictionary()呼叫.但是这段代码很乐意构建一个有效的字典并继续前进.

我有理论,但找不到确定或击落其中任何一个的确定性.并且可以通过十几种方式重写代码以避免问题; 那不是问题.我只需要知道我理解的差距是什么.

我的问题:

  1. 这段代码是否有效并且表现得如此?
  2. 如果没有,我们看到的成功是否只是一个废话?
  3. DataTable在处理对象之后是否存在允许访问的特定内容- 类似于GZipStream类要求您处理对象以刷新流的方式,因此允许在对象被处理之后.ToArray().GetBuffer()之后调用?
  4. ...当你调用方法时,实际上是什么导致抛出ObjectDisposedException?我一直认为它来自.NET框架本身.

.

澄清:

这是一个.NET Framework问题.共识是我的理解是正确的 - DataTable本身必须抛出ObjectDisposedException.除了它没有.不是DataTable源代码中的任何地方 - 因此我的要求.我假设框架将在它被处理后确保一个ObjectDisposedException,这显然不是这种情况......与GZipStream不同,GZipStream只允许在Dispose()之后访问两个方法,即DataTable DGAF.精细.

因此,让我重新解释一个问题:DataTable内部是否有任何内容可以轰炸我们,因为允许调用已分配的表?我可以假设微软没有在内部清理任何内容,只要对象在范围内,所有属性和值都将保持不变,这似乎不是一个安全的假设.这段代码无论如何都会消失 - 我只是想了解微软是否允许访问DataTable,Dispose()或者是疏忽,而不是关心等等.

此外,如果您投票或投票关闭它,请留下评论原因.

Ere*_*mez 5

我认为你缺少的部分是"处理"一个对象除了程序员在IDisposable.Dispose实现中定义的内容之外什么都不做.除了为using声明提供支持之外,语言或框架不会做任何特殊操作.

使用该using语句,语言只提供以下内容:如果您的对象实现了此特定的接口IDisposable,则它承诺Disposeusing块存在时调用该方法.而已.它不知道哪些物体已被"处置"或没有.它不会ObjectDisposedException通过以特殊方式跟踪被处置物体而抛出.

扔什么ObjectDisposedException?那么,实现该IDisposable类型的程序员需要在其中的某处编写这样的代码:

void DoMoreWork()
{
    if(_iHaveBeenDisposedAlready) 
        throw new ObjectDisposedException(null);
    ...
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下,如果以ValidationDataTable不跟踪它是否被处理的方式实现,并且它将它的数据存储在内存中,那么它将像往常一样工作.语言或框架并不能阻止这种情况发生.


更新:回答评论,它看起来DataTable不直接实现,IDisposable但它的基类(MarshalByValueComponent).他们必须继承该基类才能支持WinForms设计师的体验.在设计模式之外,Dispose不会改变任何东西.因此,您可以安全地忽略它以供正常使用.换句话说,您不需要在using块中使用它.

这是正常的吗?不可以.通常,IDisposable物体应放置在正常生命周期的某个地方.有一个IDisposable不需要处理的东西肯定令人困惑.