我有一堆 WindowsImpersonationContext 对象,它们是 IDisposable 类型。现在考虑这两个操作:
Stack<WindowsImpersonationContext> stack = new Stack<WindowsImpersonationContext>();
public void BeginOperation()
{
// Push object to stack
var context = WindowsIdentity.Impersonate(...);
stack.Push(context);
}
public void EndOperation()
{
// Pop object from stack.
if (stack.Count != 0)
{
var context = stack.Pop();
... do various stuff with 'context' ...
context.Dispose(); // should this be called once the object is not needed anymore?
}
}
如果我不想等待 GC 执行它,我应该手动调用 Dispose() 吗?如果我 100% 没有其他代码会尝试使用堆栈中引用的 context 对象,这样做是否安全?准确地说,如果我没有显式调用 context.Dispose(),我假设即使在执行从 EndOperation() 返回之后,我也任凭摆布关于处理“上下文”对象占用的资源的 GC,尽管它不再被堆栈引用?我的推理是否正确?
此外,使用上面的代码,声称在执行以下一组操作后,堆栈将在资源占用方面最终为空是否正确(即它曾经包含的所有对象都在最后处理,并且我不再需要担心在别处处理任何东西):
BeginOperation();
BeginOperation();
EndOperation();
EndOperation();
编辑:我意识到using可以/应该用于安全目的,但主要是我关心的是收集方面的背景/GC,不管语法...
请您参考如下方法:
如果您不再需要它并且它实现了 IDisposable,请使用 using 语句。
public void EndOperation()
{
// Pop object from stack.
if (stack.Count != 0)
{
using(var context = stack.Pop())
{
// ... do various stuff with 'context' ...
}
}
}
除此之外,Stack.Pop 以这种方式实现(ILSPy、.NET 4):
// System.Collections.Stack
public virtual object Pop()
{
if (this._size == 0)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyStack"));
}
this._version++;
object result = this._array[--this._size];
this._array[this._size] = null;
return result;
}
因此您看到在 Pop 之后堆栈中不再有引用。
一般来说,只要您使用非托管资源,就应该使用using(或try-finally)。通过这种方式,可以确保即使出现错误也能处理它们。
