我有一堆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背景中发生的事情,无论如何语法......
答案 0 :(得分:2)
如果您确定堆栈以外的任何内容都没有引用相关对象,那么是:您应该自己手动处理它。
我会将您的代码更改为更像这样:
public void EndOperation()
{
// Pop object from stack.
if (stack.Count != 0)
{
using (var context = stack.Pop())
{
... do various stuff with 'context' ...
}
}
}
即使在“do various stuff”块中发生异常,它也会被处理掉。
如果你不自己处理它,那么你依赖于为被处理的类实现的终结器 - 即使实现了终结器,也可能被称为太晚(想象一下它是否是一个打开的文件句柄)
答案 1 :(得分:2)
如果你不再需要它,它实现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
)。通过这种方式可以确保它们在出错时处理。
答案 2 :(得分:1)
您可以使用using
语句,但应该先实现IDisposable
。