SqlCommand.Dispose doesn't free managed object
See original GitHub issueSqlCommand.Dispose
contains this code:
// release managed objects
_cachedMetaData = null;
This doesn’t free the cached data, which is supposed to be the purpose of the Dispose(Boolean) overload when working with managed resources that don’t implement IDisposable
:
Managed objects that consume large amounts of memory or consume scarce resources. Freeing these objects explicitly in the Dispose method releases them faster than if they were reclaimed non-deterministically by the garbage collector.
By just setting _cachedMetaData
to null, the resources are only reclaimed by the garbage collector, by which time the disposed SqlCommand
object would also likely not be referenced, meaning that disposing the SqlCommand
and setting _cachedMetaData
to null is wasted effort.
This issue was observed as part of a discussion about this question: Is SqlCommand.Dispose() required if associated SqlConnection will be disposed?
Issue Analytics
- State:
- Created 4 years ago
- Comments:14 (4 by maintainers)
… that’s not really any different than adding/removing
IDisposable
. It’s actually worse, because now you have something that says “yeah, ignore this contract that I claim to need”, and if a type suddenly did have to dispose a resource (say,MemoryStream
starts allocating a native array for really large array sizes or something), your consumers now need to dispose, but you previously informed them they didn’t …A publicly visible attribute like that is likely to be permanent for the same general reason: breaking behavior change if removed.
That was my point about “could have been corrected in the transition to .NET Core”. Fortunately, there might still a good solution: Create a custom attribute (perhaps
DisposeUnusedAttribute
) that would inform developers, the IDE, and static code analysis that it’s OK to skip the extra work of adding calls toDispose
. Other classes such aMemoryStream
would benefit as well.