using (Stuff1 stf1 = new Stuff1(...)) // Allocation of stf1
using (Stuff2 stf2 = new Stuff2(...)) // Allocation of stf2
{
try
{
// ... do stuff with stf1 and stf2 here ...
}
catch (Stuff1Exception ex1)
{
// ...
}
catch (Stuff2Exception ex2)
{
// ...
}
} // Automatic deterministic destruction through Dispose() for stf1/stf2 - but in which order?
In other words, is stf2's Dispose() method guaranteed to be called first and then stf1's Dispose() method guaranteed to be called second? (basically: Dispose() methods being called in reverse order of the allocation of the object that they belong to?)
No guarantee due to possible reordering. Dispose is called on a closing curly (or an implicit one in your example). You will always see the expected order in non-optimized Debug builds. You could use Thread.MemoryBarrier to force the order of operations.
Release-mode optimizations are done in such a way as to guarantee predictable results on this thread after all instructions complete. Everything else (view from a different thread on a separate core) is up for grabs. It's not against the rules to have a situation where stf2 is not yet disposed, but stf1 is disposed, as observed from another thread. Unless you force the order of operations. Try writing some asserts and running under Jinx