I read the accepted answer to a similar question, part of the answer is:
when structs are passed as parameters, they get passed by value: they are copied. Now you've got two structs with the same internal fields, and they're both going to attempt to clean up the same object. One will happen first, and so code that is using the other one afterwards will start to fail mysteriously... and then its own cleanup will fail
Doesn't this same problem apply to Dispose()
? If structs can implement IDisposable
, what is the reasoning behind not allowing them to have finalizers?
If the whole point of a finalizer is to call Dispose(false)
in case the programmer forgot to call Dispose()
, and structs can have IDisposable.Dispose()
, then why disallow finalizers for structs but allow them for reference types?
Doesn't this same problem apply to
Dispose()
?
Sort of, but not entirely. Specifically, the "then its own cleanup will fail" is possible but unlikely, since Dispose()
must be safe to call multiple times on the same object, and it will normally not be a problem to call it multiple times on different copies of the same object.
If structs can't have finalizers, why are they allowed to implement
IDisposable
?
Allowing it is the natural behaviour; it gives the language simpler rules. Since this is not something that a programmer is likely to get wrong by accident, the benefit in writing extra code in the compiler to reject this is small.
Jeroen Mostert adds that it can even make a lot of sense for structs to implement IDisposable
:
IDisposable
may be implemented simply because it is a requirement of some other code, even though Dispose()
's implementation on this specific type will do absolutely nothing. In this case, there is no risk in accidentally calling it on a different copy. An example of this is when a struct implements IEnumerator<T>
, where IEnumerator<T>
in turn implements IDisposable
.