3 ms·
Again, that creates implicit behaviours that can be extremely surprising. You can deal with multiple Closeables by enhancing syntax. But tying deallocation to
by zzalpha 9y ago
Again, that creates implicit behaviours that can be extremely surprising.
You can deal with multiple Closeables by enhancing syntax.
But tying deallocation to disposal creates action at a distance that I'm really not a fan of, personally.
Resource allocation and deallocation can take time, can block, and can fail. Those semantics make them a terrible fit for constructors and destructors.
- btschaegg 9y agoAs a counterpoint to this: - Making it explict has the two distinct problems that a) the code for it must be written each time (I regularly encounter code that ignores Disposables) and b) is closed to change (adding a dispose semantics to a class essentially creates bugs throughout your codebase). Those two, I deem far worse than a destructor that is blocking. - On the C++ side: If you encapsulate the resource properly, you're not really binding the two together (at least on one level of abstraction), since you're basically just managing a handle. Note that it is also really easy to split both up (by introducing some NULL-handle) and only dispose the resource in the destructor if it hasn't been disposed yet (of course, that is more bug-prone, but so is IDisposable). - With move semantics (or std::swap before C++11) this also allows you to dispatch "cleanups" to other contexts, if necessary, which gives you exactly the same possibilities where necessary (of course, this also being explicit in those cases). - Failed resource allocations in constructors should not be a problem (either use exceptions or NULL-handles). - Failed resource deallocations are a problem in any implementation I know of and likely not "conquered" easily in the near future. So, to sum it up, I think C++ gives you the better tooling because you can design the appropriate API yourself. C#'s implementation is very set in it's way and has a couple of problems that would be nice to avoid (e.g. the "you can't free resources in a finalizer" thing). I'd prefer an API that does the right thing by default (albeit slow) and lets me optimize where needed instead of one that has little benefit (for most scenarios) but makes the code more error-prone. That means essentially: If you implement IDisposable in C++ and dispose in the destructor where necessary, you get the best of both approaches. The remaining arguments that then can be made against C++ are either bad code, abstraction problems and/or cumbersome libraries.