【问题标题】:How to call Dispose on a concrete implemenation of a C# class [duplicate]如何在 C# 类的具体实现上调用 Dispose [重复]
【发布时间】:2020-06-04 15:16:58
【问题描述】:

如果我使用以下结构:

public class TestClass : IDisposable
{
    private SqlBulkCopy _bulkCopy;
    public TestClass(SqlConnection connection)
    {
        _bulkCopy = new SqlBulkCopy(connection);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_bulkCopy != null)
                _bulkCopy.Dispose(); // Cannot call dispose as this is a concrete implementation
        }
    }
}

我无法访问 _bulkCopy 对象上的 dispose 函数。

我知道我可以使用using 语句,但这是唯一的方法吗?

我不希望这样做,因为这意味着我可能不得不继续重新创建这个对象

我知道我也可以围绕这个包装一个界面,但是还有其他方法吗?

【问题讨论】:

  • 将其转换为 IDisposable?
  • SqlBulkCopy 显式实现了接口,因此您必须强制转换为 IDisposable: ((IDisposable)_bulkCopy).Dispose()
  • @Selvin,正如李在我的评论中所阐述的那样,该方法确实“存在”,但已明确实现,因此需要强制转换。
  • @Lee 只要是System.Data.SqlClient.SqlBulkCopy 而不是一些具体实现 无论如何
  • 它是“在给定实现类的引用的情况下,如何调用显式实现的接口方法。”

标签: c# dispose


【解决方案1】:

这可能会发生when an interface is explicitly implemented。首先,一个隐式实现接口的基本示例:

public interface IFoo
{
    void FooTheBar();
}

public class ImplicitImplementer : IFoo
{
    public void FooTheBar()
    {
        // ...
    }
}

这可以按照您期望的方式使用,无论是具体类型还是接口:

ImplicitImplementer a = new ImplicitImplementer();
a.FooTheBar(); // works

IFoo b = new ImplicitImplementer();
b.FooTheBar(); // works

但是当你显式实现一个接口时,你必须使用接口类型。

public class ExplicitImplementer : IFoo
{
    public void IFoo.FooTheBar()  // Notice the "IFoo."
    {
        // ...
    }
}

注意后果:

ExplicitImplementer a = new ExplicitImplementer();
a.FooTheBar(); // ERROR!

IFoo b = new ExplicitImplementer();
b.FooTheBar(); // works

这就是它的工作原理。我怀疑您的SqlBulkCopy 类明确实现了IDisposable,这意味着您必须将其转换为正确的接口:

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        if (_bulkCopy != null)
            (_bulkCopy as IDisposable).Dispose();
    }
}    

我更喜欢as 语法,但如果您愿意,可以使用(IDisposable) _bulkCopy。您实际上可以在此处稍微改进代码流程:

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        (_bulkCopy as IDisposable)?.Dispose();
    }
}

这可以防止在_bulkCopy 为空或_bulkCopy 不再实现IDisposable 的情况下出现异常。如果可以,它会处理,否则它什么也不做。


为什么这很有用可能看起来很奇怪,而且在你的情况下似乎并不完全必要。显式实现仅在类实现具有冲突接口成员的多个接口时才有用,例如:

public interface IFoo
{
    void FooTheBar();
}    

public interface IBar
{
    void FooTheBar();
}

public class FooBar : IFoo, IBar
{
    public void FooTheBar()
    {
        Console.WriteLine("IFoo or IBar?");
    }
}

这段代码确实有效,但不管你是否这样做,都会调用相同的方法:

IFoo a = new FooBar();
a.FooTheBar(); // "IFoo or IBar?"

IBar b = new FooBar();
b.FooTheBar(); // "IFoo or IBar?"

但是如果你想让这两种方法分开呢?好吧,然后您将每个方法实现显式标记为属于特定接口。这就是显式实现。

public class FooBar : IFoo, IBar
{
    public void IFoo.FooTheBar()
    {
        Console.WriteLine("IFoo");
    }

    public void IBar.FooTheBar()
    {
        Console.WriteLine("IBar");
    }
}

然后你会看到:

IFoo a = new FooBar();
a.FooTheBar(); // "IFoo"

IBar b = new FooBar();
b.FooTheBar(); // "IBar"

但是由于您已将这些方法限制为特定的接口,FooBar 本身无法再解析为特定的FooTheBar 方法,因此您将面临错误。这是解决另一个问题(即重叠接口)的结果。

【讨论】:

    猜你喜欢
    • 2019-06-03
    • 2016-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-06
    相关资源
    最近更新 更多