gpt4 book ai didi

c# - 引用 using() block 之外的对象

转载 作者:行者123 更新时间:2023-11-30 17:38:23 25 4
gpt4 key购买 nike

SO 上有很多关于这个主题的问题,但我还没有找到一个涵盖我特别需要了解的内容。

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

//

// 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...

//

我的理解:在最后一行代码中引用 validationTable 时,它​​已被释放但未被垃圾收集——但仍应在 .ToDictionary() 上抛出 ObjectDisposedException > 打电话。但是这段代码愉快地构建了一个有效的字典并继续运行。

我有一些理论,但找不到任何确定的东西来证实或否定其中的任何一个。并且可以通过多种方式重写代码来避免该问题;这不是问题。我只需要知道我的理解差距是什么。

我的问题:

  1. 此代码是否有效且行为正常?
  2. 如果不是,我们看到的成功是否只是胡扯?
  3. 是否有关于 DataTable 的特定内容允许在处理对象后访问 - 类似于 GZipStream 类要求您处理对象以刷新流,因此允许在处理对象后调用 .ToArray().GetBuffer()
  4. ... 在您调用方法时究竟是什么导致抛出 ObjectDisposedException?我一直认为这是来自 .NET 框架本身。

.

澄清:

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

那么让我重新表述一下这个问题:DataTable 内部是否有任何东西会轰炸我们,因为允许调用已处置的表?我可以假设 Microsoft 没有在内部清理任何东西,只要对象在范围内,所有属性和值都会在那里,不会受到影响——这似乎不是一个安全的假设。这段代码无论如何都会消失 - 我只是想了解 Microsoft 是否有意允许在 Dispose() 之后访问 DataTable,或者这是疏忽,不关心等等。

此外,如果您对问题投反对票或投票关闭它,请留下评论原因。

最佳答案

我认为您缺少的部分是,“处置”对象除了程序员在 IDisposable.Dispose 实现中定义的内容外,不会执行任何其他操作。除了为 using 语句提供支持外,该语言或框架没有做任何特殊的事情。

通过 using 语句,该语言仅提供以下内容:如果您的对象实现了这个名为 IDisposable 的特定接口(interface),那么它 promise 调用 Dispose 方法,当它存在于 using block 时。就是这样。它不知道哪些对象已被“处置”或未被处置。它不会通过以特殊方式跟踪已处置的对象来抛出 ObjectDisposedException

是什么引发了 ObjectDisposedException?好吧,实现 IDisposable 类型的程序员需要在某处编写这样的代码:

void DoMoreWork()
{
if(_iHaveBeenDisposedAlready)
throw new ObjectDisposedException(null);
...

因此,在您的情况下,如果 ValidationDataTable 的实现方式不跟踪它是否已被处置,并且将其数据存储在内存中,那么它将正常工作照常。语言或框架并不能阻止这种情况发生。


更新:为了回答评论,看起来 DataTable 没有直接实现 IDisposable 但它是基类 (MarshalByValueComponent)。他们必须从该基类继承以支持 WinForms 设计器体验。在设计模式之外,Dispose 不会改变任何东西。所以你可以安全地忽略它来正常使用。换句话说,您不需要在 using block 中使用它。

这正常吗?不。通常,IDisposable 对象应该在其正常生命周期的某个地方被处置。拥有一个不需要处置的 IDisposable 肯定会让人感到困惑。

关于c# - 引用 using() block 之外的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36751989/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com