In a company that I used to work for, developers loved to use null-conditional operators everywhere 'just in case' and that code was a nightmare to debug, because of those null-conditionals masking the real problem and leaving you with totally unrelated null reference exceptions much later.
Yes, I've heard of situations where the null conditional operator has introduced bugs. Yesterday on one of my teams a dev had used it and I was explaining why she should remove it and that went on to an interesting conversation. I think I'll make video on this topic :)
Thank you for the video, really well explained. I have a question: Does it make sense to use IDisposable on Singletons? I thought Singleton Instances live for the lifetime of the whole application and after the application shuts down, the os would free up the resources. So what's the reason to use IDisposable on Singletons?
I commend you for taking on this fascinating topic! I always thought finalizers should be added to our disposable classes, with the hope they will not be used. For example, if a programmer uses our class but mistakenly forgets to call Dispose(), then the instance remains on the freachable queue where eventually threadpool threads execute the queued finalizer(s) to properly dispose our object(s) and then removes the root reference to our instance so it can eventually be garbage collected. As you said, that's why we need SuppressFinalize(), so that finalization can be skipped and memory used by the object can be recompacted much sooner. IMHO, disassembling the Close() and Dispose() methods of the used data provider connection object is recommended to see what is really happening under the covers. Many times Dispose() calls Close() for us automatically. BTW - there are some real garbage collection nerds out, even GC publications and conferences. I'm still a novice but I'm fascinated with the science. Digging into memory pressure and generation counts could be a whole other video. Thank you, Shiv, for the great video!
Hi Davin, >I always thought finalizers should be added to our disposable classes, with the hope they will not be used. That could be a viable strategy, though I've never used it (or seen it used) myself. So do you call the private Dispose(bool disposing) method passing in false as the argument from your finalizer? Yes, Dispose calls Close. I guess the point was really trying to make was that they do different things (close releases the connection back to the pool). In my actual code on GitHub, I don't actually call close. I simply dispose.
@@Matlus Yes - the finalizer typically passes false to Dispose() to release the unmanaged resources (file handles, window handles, libraries, etc.) Thank you, sir.
I like how you pay attention to this nullability detail at 18:30. In my project that i work on people are overusing this operator just to supress warnings:(
It's good to mention that the AppDomain is only used in the (old/legacy) dotnet Framework. Dotnet Core and .NET5 and .NET6 do not use AppDomains. It's also good to know that the dispose pattern is only there for derived classes to be able to call all the dispose logic of the entire class hierarchy in combination with Finalization. If your class is sealed (as in this example) it cannot be derived from and you do not need to implement the dispose pattern.
Hi Marc, good point about sealed classes and the dispose pattern, I should have made mention of it, true. However, I implement the pattern in sealed classes nonetheless. As regards AppDomains, they're still there. You can't create (more) app domains like you could in earlier versions. At least that's how I understand it.
Welcome Back Shiv :) Can you please clarify the "AppDomain" difference between a console application and a Asp.Net web application ? How and why in the latter case, my code is running in multiple AppDomains ?
Thank you Johnny! ASP.NET applications run in another process (a worker process called W3p.exe) and generally, for a given "Web Application" you'd configure your web application to use multiple worker processes to handle the workload. Typically one per the number of CPU cores available on the server. Thus your application is running in multiple app domains (one per worker process). Hopefully that makes sense?
Best explanation I've found about IDisposable. Thank you!
Great video and topic as always, one of the few channels here on RUclips that deliver professional in-depth content
Thank you Arghs! Your comment is much appreciated.
Great video! Havent seen anybody who has digested the stuff and can explain it so clearly and calmly.
Thank you Suhasini! Glad you liked it and found it useful.
Looking forward to that video - let's see if I can learn one or two new things. Thanks for your time Shiv.
Hi Hans, let me know what you think!
In a company that I used to work for, developers loved to use null-conditional operators everywhere 'just in case' and that code was a nightmare to debug, because of those null-conditionals masking the real problem and leaving you with totally unrelated null reference exceptions much later.
Yes, I've heard of situations where the null conditional operator has introduced bugs. Yesterday on one of my teams a dev had used it and I was explaining why she should remove it and that went on to an interesting conversation. I think I'll make video on this topic :)
Thank you for the video, really well explained. I have a question: Does it make sense to use IDisposable on Singletons? I thought Singleton Instances live for the lifetime of the whole application and after the application shuts down, the os would free up the resources. So what's the reason to use IDisposable on Singletons?
I love your videos
I commend you for taking on this fascinating topic!
I always thought finalizers should be added to our disposable classes, with the hope they will not be used.
For example, if a programmer uses our class but mistakenly forgets to call Dispose(), then the instance remains on the freachable queue where eventually threadpool threads execute the queued finalizer(s) to properly dispose our object(s) and then removes the root reference to our instance so it can eventually be garbage collected.
As you said, that's why we need SuppressFinalize(), so that finalization can be skipped and memory used by the object can be recompacted much sooner.
IMHO, disassembling the Close() and Dispose() methods of the used data provider connection object is recommended to see what is really happening under the covers. Many times Dispose() calls Close() for us automatically.
BTW - there are some real garbage collection nerds out, even GC publications and conferences. I'm still a novice but I'm fascinated with the science.
Digging into memory pressure and generation counts could be a whole other video.
Thank you, Shiv, for the great video!
Hi Davin,
>I always thought finalizers should be added to our disposable classes, with the hope they will not be used.
That could be a viable strategy, though I've never used it (or seen it used) myself. So do you call the private Dispose(bool disposing) method passing in false as the argument from your finalizer?
Yes, Dispose calls Close. I guess the point was really trying to make was that they do different things (close releases the connection back to the pool). In my actual code on GitHub, I don't actually call close. I simply dispose.
@@Matlus Yes - the finalizer typically passes false to Dispose() to release the unmanaged resources (file handles, window handles, libraries, etc.)
Thank you, sir.
Cool!
I like how you pay attention to this nullability detail at 18:30. In my project that i work on people are overusing this operator just to supress warnings:(
Thanks for writing in and confirming that this sort of thing happens a lot.
It's good to mention that the AppDomain is only used in the (old/legacy) dotnet Framework. Dotnet Core and .NET5 and .NET6 do not use AppDomains.
It's also good to know that the dispose pattern is only there for derived classes to be able to call all the dispose logic of the entire class hierarchy in combination with Finalization. If your class is sealed (as in this example) it cannot be derived from and you do not need to implement the dispose pattern.
Hi Marc, good point about sealed classes and the dispose pattern, I should have made mention of it, true. However, I implement the pattern in sealed classes nonetheless.
As regards AppDomains, they're still there. You can't create (more) app domains like you could in earlier versions. At least that's how I understand it.
Welcome Back Shiv :)
Can you please clarify the "AppDomain" difference between a console application and a Asp.Net web application ?
How and why in the latter case, my code is running in multiple AppDomains ?
Thank you Johnny!
ASP.NET applications run in another process (a worker process called W3p.exe) and generally, for a given "Web Application" you'd configure your web application to use multiple worker processes to handle the workload. Typically one per the number of CPU cores available on the server. Thus your application is running in multiple app domains (one per worker process). Hopefully that makes sense?
@@Matlus That's making it crystal clear!
Thank you Shiv
Great video: only 13k subs ? :-(
Tks...
You're welcome Glayson.