So I was just reading about the RAII pattern for non garbage collected languages, and this section caught my eye:
This limitation is typically encountered whenever developing custom classes. Custom classes in C# and Java have to explicitly implement the dispose method in order to be dispose-compatible for the client code. The dispose method has to contain explicit closing of all child resources belonging to the class. This limitation does not exist in C++ with RAII, where the destructor of custom classes automatically destructs all child resources recursively without requiring any explicit code.
Why is it that C++ can correctly track these resources that are allocated in the RAII pattern, but we don't get this lovely Stack Unwinding with the C# using construct?
Suppose an object O is composed of two resource-owning objects R and S. What happens if O is destroyed?
In C++ with RAII, objects can own other objects such that one object's destruction is necessarily coupled to the other's. If O owns R and S -- by storing them by value, or by owning something which in turn owns R and S (unique_ptr, container that stores R and S by value), then destruction of O necessarily destroys R and S. As long as the destructors of R and S properly clean up after themselves, O doesn't need to do anything manually.
In contrast, C# objects do not have an owner that decides when its lifetime ends. Even if O would be destroyed deterministically (which it generally isn't), R and S might be reachable by another reference. What's more, the way O refers to R and S is the same way any other local variable, object field, array element, etc. refer to R and S. In other words, there's no way to indicate ownership, so the computer can't decide when the object is supposed to be destroyed and when it was only a non-owning/borrowed reference. Surely you would not expect this code to close the file?
But as far as the CLR is concerned, the reference from the local
fhere is exactly the same as the reference from O to R/S.TL;DR Ownership.