Cleaner C# code with "smart" using statements

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody i'm nikken in this video i'm going to show you a different way of using the using keyword in c sharp and that is in the context of disposing an object and i'm going to show you why it can lead to some cleaner code with that pretty smart usage in my opinion if you like type of content and you want to see more makes you subscribe running this notification bell and for more training check out nickchapters.com now before i move on i want to let you know that i just launched my from zero to hero dependency injection in dotnet cores in that course i take you from the very basics of dependency injection to the fundamentals we do a deep dive into the di framework itself we see how we can use some pretty advanced patterns and approaches with the built-in di framework then see how we can extend it even further to add other behaviors and then to top it all off we build the dependency injection framework from scratch this is by far the most complete dependency injection course you will find out there trust me i checked all of them and will teach you everything you need from the very basics to some pretty pretty advanced stuff and it all comes from real world experience building huge scale microservices now the first 100 of you who want to buy this course can use this code right here to get 15 off so check it in the description but if you want and thank you very much for supporting the channel so let's take a look at the project we will be applying this technique on so all i have here is a weather forecast controller and even though it looks kind of you know the same as the built-in one we actually use um open weather forecast i think that's what the name is to get um the actual weather so if i go here we have an api key which will be long gone by the way so don't even try and then we make the api call to that service and if we get the weather back we return it if not we return nothing and if very quickly i run this just to show you how it looks like um i'm gonna open postman and as you can see i'm getting the weather back for london now this is great and all but here's the thing what if i wanna have a measuring mechanism to see how long this call over here takes or maybe this call over here or maybe on the controller level this call over here there's many ways to go about this but just to deconstruct the basics of this let's go here and let's say i want to measure how long this bit here takes so the most basic way you would probably do this is you'd have a try here and you would place all that in that triangle and then you'd have a finally block and in that final block is where you do your logging so you would have something like a stopwatch here and by the way yes this is not using a library there are libraries that can do that but we want to see what problem we're really solving behind the scenes so you can reuse it in your own examples so we have the stopwatch here and we're starting a new one then this call will happen and because finally block will execute at the end we can say stopwatch dot and stop oh that's a start we want to say stop here we go and then we want to log that so i injected an i logger here comes with the framework and i can say logger.log let's say information here and then first comes the message so i can say weather retrieval for and let's say london here completed in and then the second argument is the time so we would say city which comes from the method arguments and then the second is stopwatch dot elapsed milliseconds and this should also say ms so once we have that if i run this api again i go back here and i call it um as you can see now this returns the message i wanted weather retrieval for london completed in 148 milliseconds and if i repeat it it's faster because of caching and stuff so that does what we want right and if we want to measure other things let's say back here i could drop the calls i want with this try finally mechanism and i can measure anything now here's the thing this is quite a bit of code and there's also quite a bit of nesting as well we have this try thing and then we have the final block and then the stopwatch has to be outside so it can be in scope for both this and this and it's just weird it's a bit clunky and reusing it even though possible you're probably gonna have to write something like a delegate to pass this in there that can cause closures and scope problems and it's kind of a mess now here's where the using keyword comes in and for those of you who don't know the using keyword um isn't real what do i mean by that well let's go ahead and make a simple class here just to to prove something i'm going to say example class here yes i want to add this and i want to stop this from running and i'm going to say public void we just want to demonstrate something so test so let's say that i have an http client right so new http client now the http client if we go into the source code for this class implements any time now if i go to here we go it implements the message invoker which implements the i disposable so when something implements the id is possible means that it can use the using keyword and traditionally you would use that keyword and what this does is because you might not need this client later and it needs to be disposed in a special way because it involves io network in this case outside of this scope the i disposable method will be called automatically now this is true for things like databases file system calls network calls anything that needs special disposal that can be just you know gob is collected and be done with it could use this assuming and that's important you understand how its scope works for example you could reuse an http client that and that's totally fine you don't have to dispose them you can also technically reuse a singleton um db connection for some db's that are okay with it so you don't need to dispose everything but if you know what you're doing this will make sure that this client wants out of this scope will be disposed how does it do that well like i said the using keyword is not real what do i mean by that well what i mean is that this what you're seeing here which by the way now can be written as this so we can remove the nesting and now you have this top level uh sort of using statement approach which the way it works is it assumes that the scope of this method is this area here the basically the bottom um curly brace that's the scope this is the equivalent of you going ahead and writing this var client equals new http client then try and no exception that doesn't exist finally and then in the end in here it would do a null check and we'll call the dispose method that's all it really does that's what the using statement really translates into and actually we can prove that i'm going to go ahead and open shoplab.io which i've talked about in the past but it is a a website that allows you to see that lord code and what i can do is i can say public class my disposable and i'm going to create a class that implements i disposable right and i'm going to go ahead and implement the dispose interface this post call so we have our own thing implementing how disposable and now in that m method i'm going to say using var disposable equals new my disposable right look what happens on the right where you see the lowered code of the compiler will generate before it compiles to il so my disposable is out here exactly like i showed with the http client then the try method is where things like this um will actually be so if i say right line then that goes in here right so you can see the link here and then the finally we'll ensure that this thing is disposed immediately after we're outside of this scope that's that's all there is to it it's just syntactic sugar like so many things we can leverage this however to do some interesting stuff and this is where the fun starts so i'm gonna go ahead and delete this class here and i'm gonna go back to this code if you're anything like me you're probably thinking hey something outside of trying finally something in finally you don't have to dispose anything but technically we can leverage that behavior for something nice let's see what we can do i'm going to go ahead and create a logging directory here so logging and i'm going to create a couple of things first i'm going to create a new class and i'm going to call that timed log operation right because what we want is a way to log things in a timed manner within a scope so that can now implement i disposable you see where i'm going with this so what we need here is an i logger of type t so i'm going to go ahead and add t here and that is our logger and this can be read only as well it doesn't need to be mutable and then we need a we could have a log level so let's say log level is this but we're probably going to use information for this demo then we need the message itself so string message underscore and then we have private read only um and that's an array of nullable objects which is the arguments so args uh and do we need anything else we need the stopwatch so this is read-only stopwatch cool so logger is implemented we do not need the stopwatch so everything else should be implemented in here and then let me just make this like this so you can see it and then for the stopwatch we can just say stopwatch equals stopwatch.start new so now watch what happens we have this stopwatch stop and logging thing we can join that from here and put it in the dispose method because the disposed method is guaranteed to be called when the using thing goes out of scope because it will be forced to be disposed so we can say stopwatch.stop and we're going to change that a bit we're going to say log here to make it more generic and then we're going to change that to underscore log level and then we have the message the message doesn't need to be this so we can delete that it can be message and we can use string interpolation here to have message um completed in and then sw dot last milliseconds which is really stopwatch here here we go and in the end just underscore args and that's it and now we're gonna go ahead and create a new class here and we're gonna call that logger extensions and we're gonna make this a static class and we're gonna add a public static method that returns i disposable interesting right and this will be timed operation and it will accept a few things first it will accept this logger and that's gonna be of type generic t so here logger and then we're gonna have the string message and the params of um nullable objects here we go args and all it does is it returns a new timed log operation of type t of course and that accepts the logger we're gonna default on information level for this demo and then message and args now watch this i can go back to the service and all this code that you see all this fluff can be deleted here we go this goes away and this goes away and the nesting goes back here and i can say using var underscore to discard the value equals logger dot timed operation for some reason this was not picked up correctly because this is logger i need i logger here fine so this is now timed operation and then message was whether for the city was london so but actually how was this worded before uh that let's just copy that the way it was so weather retrieval for that so let's do that let's let's fast forward and say whether we dribble for that and this will add automatically in the end the completed n part so now if i go ahead and run this watch what happens go back here execute that and it still has everything we had before weather retrieval 4 london completed in 142 and this is coming from this code because the dispose method is called and in fact let's just debug this so take off the debugger stick a breakpoint here and go ahead and call that endpoint again and as you can see we go in here so this creates the object and the object is disposed because we didn't need it and then it steps into the dispose method automatically and now if we want to go ahead and add that sort of logic anywhere else like let's say the controller you want to log something you can say using var underscore equals and then i have the logger so timed operation and you know get weather so let me just say name of this and do that and then if i run this i'm going to go ahead and i get both so get weather completed in 140 milliseconds because this is this and if i go higher i'm sure there's that other call as well uh logged yeah here we go so it's a very generic way of doing something pretty smart i think and it it makes use of a mechanic of the language for your own benefit which i find pretty interesting and you can actually do way more things than just this with it but the main idea is to understand how the code is lowered how this pose is called and how you can leverage that and of course nothing says you have to use the top level scope thing if you only want to time let's say a different thing like another scope thing you can do this and then let's say i only want to time i don't know the responses how how they are mapped i can say this and then i can put them in here and then the timer is only here or you can take that and put it here ultimately it's completely up to you you have full control now and you can scope this any way you want and this is significantly less code than what we had before and also it's way more reusable so this is what i want to show you it's a very smart way i think to use the using keyword and i'm interested to see what you can do with it so please let me know down in the comments well that's all i have for you for today thank you very much for watching special thanks to my patreons for making videos possible if you want to support me as well you're going to find it in the description down below leave a like if you like this video subscribe welcome to like this sharing the bell as well and i'll see you in the next video keep coding
Info
Channel: Nick Chapsas
Views: 63,771
Rating: undefined out of 5
Keywords: Elfocrash, elfo, coding, .netcore, dot net, core, C#, how to code, tutorial, development, software engineering, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, clean code, dotnet, using keyword, using statement, using c#, c# using statement, using .net, using, using disposable, idisposable, disposable pattern, c# idisposable
Id: iqt7bqAm27U
Channel Id: undefined
Length: 16min 30sec (990 seconds)
Published: Thu Dec 23 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.