C# has the advantage of being a typed language, which allows compilers and IDEs to warn in the circumstances I mentioned. JavaScript isn't a typed language, which limits the potential for such warnings.
Anyway, I didn't say it was "inferior to defer", I said that it seemed more error-prone than RAII in languages like Rust and C++.
Edit: Sorry if I'm horribly wrong (I don't use C#) but the relevant code analysis rules look like CA2000 and CA2213.
> Anyway, I didn't say it was "inferior to defer", I said that it seemed more error-prone than RAII in languages like Rust and C++.
It is, but RAII really isn't an option if you have an advanced GC, as it is lifetime-based and requires deterministic destruction of individual objects, and much of the performance of an advanced GC comes from not doing that.
It’s still difficult to get right in cases where you hold a disposable as a member. Its not obvious if disposables passed in also get disposed and what’s right depends on the situation (think a string based TextWriter getting passed in a byte-based Stream) and you will need to handle double disposes.
Further C# has destructors that get used as a last resort effort on native resources like file descriptors.
> Further C# has destructors that get used as a last resort effort on native resources like file descriptors.
True, I was going to mention that, but I saw that JS also has "finalization registries", which seem to provide finalizer support in JS, so I figured it wasn't a fundamental difference.
As a practical matter it's easy to forget in C# and it's up to you to remember. Those two analyzers are disabled by default and prone to both false positives and false negatives. They hardcoded the known behavior of a bunch of .NET classes to get it to be usable at all.
Anyway, I didn't say it was "inferior to defer", I said that it seemed more error-prone than RAII in languages like Rust and C++.
Edit: Sorry if I'm horribly wrong (I don't use C#) but the relevant code analysis rules look like CA2000 and CA2213.