When using lambda functions, it is often convenient to pass around instances of Action<> or Func<>. In combination with the ‘using’ keyword, scoping can get a very flexible feature. Just a simple struct helps capturing Actions as an IDisposable:
public struct DisposeAction : IDisposable { readonly Action _action; public DisposeAction(Action action) { _action = action; } public void Dispose() { _action(); } }
Now, imagine for example a stack where you want to push an element temporarily on:
var stack = new Stack<int>(); stack.Push(42); useTheStack(stack); stack.Pop();
Seems fine, but it’s not complete yet. We want the stack cleaned when an exception is thrown in ‘useTheStack’:
var stack = new Stack<int>(); stack.Push(42); try { useTheStack(stack); } finally { stack.Pop(); }
Admittedly, this is a frequently recurring pattern that can be spotted in C# code. But with the above DisposeAction, we can do better:
public static IDisposable scopedPush<E>(this Stack<E> stack, E element) { stack.Push(element); return new DisposeAction(() => stack.Pop()); }
The above code can now be replaced by:
var stack = new Stack<int>(); using (stack.scopedPush(42)) useTheStack(stack);
Fine, and we get the try/finally for free :)