Earlier quoted context omitted.
In C# the closest analogue to a C++ destructor would probably be a `using` block. You’d have to remember to write `using` in front of it, but there are static analysers for this. It gets translated to a `try`–`finally` block under the hood, which calls `Dispose` in `finally`. using (var foo = new Foo()) { } // foo.Dispose() gets called here, even if there is an exception Or, to avoid nesting: using var foo = new Foo(…
That approach doesn't allow you to move the file into some long lived object or return it in the happy path though, does it?
In addition, if the caller itself is a long-lived object it can remember the object and implement dispose itself by delegating. Then the user of the long-lived object can manage it.