c# - IDisposable 字段怎么能在这里为空?

标签 c# null dispose

我有很多例子表明一次性类使用空条件运算符(如 _field?.Dispose())处理其一次性字段。 Resharper 还会生成带有空检查的代码。

class Foo : IDisposable
{
    private readonly Bar _bar;

    public Foo()
    {
        _bar = new Bar();
    }
    
    public void Dispose()
    {
        _bar?.Dispose();
    }
}

class Bar : IDisposable
{
    public void Dispose()
    {
    }
}

我的问题是为什么这里使用字段 _bar 的空检查?此时它不能为空。它不会被垃圾回收,除非包含对象被垃圾回收,因为它持有对它的引用。如果包含对象,即 Foo 对象为空,我们永远不能对其调用 .Dispose(),因为它会抛出空引用异常。

最佳答案

你说得对,_bar 在此特定示例中不能为 null。这是几个因素的组合:

  • 只有一个构造函数总是初始化一个Bar对象
  • _bar 是只读的,这保证之后没有人可以将它设置为 null

但不难想出一个它可能为 null 的示例(例如,更改上述任何要点)。即使对于这个简单的代码示例,我也已经争辩说,如果您希望它成为一个干净的代码库,则很可能应该注入(inject) Bar ,这抛出了您可以保证 _bar 的论点 不会为空。

专门创建代码的 null 保护和非 null 保护变体与始终防止 null 相比有什么好处?这需要更多的努力,您可能会选择错误的选项;有什么好处?什么都没有。

因此,如果故意省略 null 保护没有任何好处,为什么还要费心弄清楚是否有必要防止 null 呢?只包含空值保护比花时间弄清楚在这种特定情况下是否不需要空值保护要容易得多。

另请注意,您具体指的是在线演示代码或 Resharper 生成的模板,这两种情况都旨在覆盖广泛的受众并保持广泛适用。

关于c# - IDisposable 字段怎么能在这里为空?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64513257/

相关文章:

c# - 将一定数量的行从 DataReader 加载到数据表中

c# - 获取首先实现接口(interface)但没有派生类的所有 c# 类型

c# - 将值添加到行、检索它们并拆分它们

sql - UPDATE ON CONFLICT 查询时发生 NOT NULL 约束冲突

c# - 使用一次性模式清理 IDispose 成员类

c# - .NET 4.x 相对于 .NET 3.5 更改了小数点 - 如何修复? (统一)

php mysql 查询资源 null 错误

c - 使用 sprintf 时大小为 1 的 char 数组的空终止

c# - 返回具有非处置内存流的对象会导致内存泄漏?

c# - 如何从 C# 面板控件中 Dispose() 特定用户控件?