如何在 C# 的具体实现上调用 Dispose class
How to call Dispose on a concrete implemenation of a C# class
如果我使用以下结构:
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
对象上的处置函数。
我知道我可以使用 using
语句,但这是唯一的方法吗?
我不想这样做,因为这意味着我可能不得不继续重新创建该对象
我知道我也可以围绕它包装一个接口,但还有其他方法吗?
这可能会发生 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
class 显式实现了 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
为 null 或 _bulkCopy
不再实现 IDisposable
的情况下出现异常。如果可以,它会处理,否则什么都不做。
为什么这有用,这似乎很奇怪,而且在您的情况下似乎也没有必要。显式实现仅在 class 实现具有冲突接口成员的多个接口时才有用,例如:
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
方法,因此您会遇到错误。这是解决另一个问题(即重叠接口)的结果。
如果我使用以下结构:
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
对象上的处置函数。
我知道我可以使用 using
语句,但这是唯一的方法吗?
我不想这样做,因为这意味着我可能不得不继续重新创建该对象
我知道我也可以围绕它包装一个接口,但还有其他方法吗?
这可能会发生 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
class 显式实现了 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
为 null 或 _bulkCopy
不再实现 IDisposable
的情况下出现异常。如果可以,它会处理,否则什么都不做。
为什么这有用,这似乎很奇怪,而且在您的情况下似乎也没有必要。显式实现仅在 class 实现具有冲突接口成员的多个接口时才有用,例如:
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
方法,因此您会遇到错误。这是解决另一个问题(即重叠接口)的结果。