5 Tips and potential MISTAKES that you SHOULD know about, for C# and .NET

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody I'm Nick and in this video we're gonna take a look at five things that you should know about in dotnet and c-sharp these are tips and tricks but will generally make your code better or run faster and there are also things that you might not know that you're doing wrong these are the five topics I'm going to cover in this video so if you're familiar with one of them based on the title feel free to skip to move to the one you're interested in by using the timestamps below this video is part of my five useful dotnet tips and tricks series so if you don't want to miss any episode please subscribe like this sub notification well to get notified when I upload a new video so let's start with the first one which is that acing actions are not awaited in c-sharp what I have here is a main method and main async task method and within that I have another method that I own it's a static method here and then this method has an action as a parameter so what happened in this piece of code is that I am a sinking this action that you see here which contains a task delay and a console dot write line test so just by looking at the code what this should be doing is awaiting this method desizing method which has its own delay it's a fake delay to pretend like it's doing some stuff and then I'm a sinking the action that's happening here with its own delay for a second and then I'm putting something to the console so if I go ahead and run this using the debugger as you can see I don't actually see anything printed so this is where something's clearly wrong here to understand what's happening here let me give you a bit of an example of what an action it's very quickly so effectively what you see an action being here is very simply a public void test method so an action is effectively a delegate that doesn't return anything and it can actually accept things as what so if I have a string here for example then it's the same as this in the same way that if you turn avoid to a sink you have an event and not an actual task and action cannot be awaited because it's treated as an event meaning that even if you have a sink stuff and you await the execution of it as a lamp has a delegate here will not be awaited so how do we fix this problem and actually I've seen this in many Newgate libraries and I've seen in many different code bases were so this is a very common one so what do we do to fix that well first and foremost you're gonna go to the action and you want to simply change that from a an action to a function func that returns a task and now you can actually properly outweigh it internally as well and what this will do now and as you can see I'm gonna run this is it will wait for one second in here and they'll print the test so now properly the code will be async and it will be awaited before the program finishes executing so this is one of the very common tricks just that async actions are not unweighted because it treated as events and that's the first tip of the video now for the second tip we're gonna take a look at get or add in the concurrent dictionary is actually not thread safe so let's take a closer look to this method now for those who don't know the concurrent dictionary is a version of the dictionary collection which is generally thread safe the weight achieves that is that it's methods are effectively locking meaning they prevent other threads to access them an example would be that something like the dictionary dot try a door try get or update or try remove they all internally if I quickly D compile the code and step into the code they will acquire a lock as you can see the pointer is entering here and they will only allow one thread to manipulate that the problem is that one of the most common methods of the diction is the get or add method what this method is doing is it accepts a key let's say key here and then it accepts a value factory or a value but usually used with the value factory and this value factor is very similarly a function that accept a string and returns the string that you want to add and what it's doing is it's checking for this key if there is a value in the dictionary if it is it returns it if it's not it will use this instruction this function here to create it and add it so it's effectively one call to do two things at check and an add now the problem with this method is that it is not actually thread safe and we can very easily prove that we can simply run this in the debugger and you will see that what you get here is actually pretty normal right because what do you expect what I have in the code let me just explain it what I have in the code is a two task daughter runs which will asynchronously run two tasks and then I'm gonna await them so they will execute in parallel here and there will be a waited until they're completed and then a synchronous one where I'm just am adding some key and all I'm really doing is I'm adding this value into the dictionary so this is all it's doing it's taking some value it's using the same some key key and then it's adding something as its value you know you can see by this returning first call three times but what happens is the first call task completes first so it adds the missing value and then the rest of the calls are being node and what happens is is just getting the value using the key and returns it now if I run this again and just to make this clear I'm gonna run this a couple of times as you can see now it returns the second call this is fine the reason why this is happening is because of this task running in parallel one of them will run first and it's very likely that the second call will actually run first and then the first one will run second so you will not see here the problem is not that this is expected behavior the problem is that if I create a private static let's say visitor count and set it to zero and this needs to be of course an integer and I put that into the method right before the call text and I say I could say increment but this is not thread safe so what I'm going to do instead is I'm going to use the interlock plus interlocked dot increment and then I'm using the reference of what I want to increment and this will effectively do the same plus plus increase but in the thread side fashion and at the end I am going to do console dot write line called and let me just use this feature called visitor count times now if this was for it safe what I want to say is this thing called 1 times if I see 2 times this will mean that it's not read safe and I expect it to not be because this method is not read safe it's not acquiring any lock how can we fix this well this is very important there's a very easy and clever way to do this what you want to do is instead of having a dictionary of string and the thing you want to store you want to have a dictionary of your key type and the lazy version of the type you want to return the reason why you do that is because having the lazy there won't do any compute as it's adding it so it will only be called once it's a weird a nice mechanism but I'm gonna link a link in the description down below explaining this process in depth and I'm gonna keep this here but what I want to do like I said is I wanna and let me just quickly delete that is I wanna return a new lazy string here and I'm gonna use the function approach and I'm gonna just paste the same code actually right here so this is the code we had before let me just reformat it real quick so same thing now to lazy and instead of printing the call value we need to do the dot of value and this dot value is what will effectively trigger the lazy class to be computed let's go ahead and run this now and as you can see it is only called one x remember this does not guarantee that this will come first and this will come second this is running in parallel there is nothing we can do a run that I mean technically the risk but we don't care what we care about is this method being called one time's the delegate method that builds the value for the key to be called one time and I can run this again you can see that now it says second call this is because it will not guarantee ordering but it will guarantee that it's only visited one time on and this is an issue I see all the time as well it's a very common one very easy to fix just use lazy and the time you want to return and don't call value until you actually need it now for the third one we're gonna go to something you might actually be familiar with this is a very common one but I want to show you a better way to do what we've already been doing until now so what you have here is you have a project which has a single class it is a a class to test and it only has internal class is an internal method and the internal method boolean is a snake creating YouTube videos return true very simple method and I also have a test class for this now usually the naming convention for test classes for this project actually is the name of the project that what you want to test belongs into and then dot tests at the end this is the naming convention I've seen widely used and I like using it as well so in this example test class what you might want to do is test this internal method now remember internal is not like private private methods should be tested indirectly by using the public methods that are calling them internal methods are effectively like public methods but you're hiding them from the consumer because they don't need to know about them but your code needs to know about them in order to test them there is no other way if they're not exposed publicly and it could be very complicated to expose them publicly so what you want to do instead is you want to create a new class here and you can call this whatever I'm gonna call it internals visible or something it doesn't really matter and what I want to do is I'm gonna delete everything that it contains and I'm gonna say assembly internals visible to and then I'm just gonna use the project name that I want the internals of this project to be visible to in this specific scenario its internals visible for dot tests and actually let me just comment this out and go back to the example tests and I'm gonna say test class equals new class to test and as you can see what I'm getting is a warning saying that you cannot access an internal class here so what I'm gonna do instead is I'm gonna go and and comment this assembly internal is visible to you and as you can see going here unless I misspell that I totally missed out that let me just copy this and paste it yeah I missed there for test stuff so if I go back now I can access it and now I can call the private methods and this should be true now this is a nice work dude but I think there's an even nicer way to do this we're gonna go ahead and delete this class and now again this is unreachable this is internal and what I'm gonna go instead and do is I'm gonna go into the CS profile and I'm going to add a new item group and in this item group I'm gonna create an assembly attribute which instructs it to include the following namespace and let me just copy that because it's boring to just same type down and this namespace is actually the same namespace that the internals disabil to class that we used belong to in the class we just delete it and the whole point of it is to just provide this basically here you you need to say underscore parameter one because we need to provide the parameter for this class for this assembly attribute and all we need to say is dollar sign assembly name and this is effectively a variable it will use the assembly name here dot tests and assuming you're using the convention that I talked about the dot test convention as you can see now magically with code our class is accessible of course if you are not using the convention you're gonna have to go ahead and actually type the thing you want this to be visible to you and this will also work but I prefer this because you can just have it as a templated thing in your project and then automatically or your internals will be visible to anything that you want to test this project with so that is for number three now the fourth one is called auto property versus expression bodied members let's take a look at the employee class here so what you have here is an employee class with a constructor which gets the first and the last name of a user and then it uses effectively what is called an expression bodied member to concatenate the first name and the last name to create a full name now I know this is not the proper way to do the full name but just for the sake of this example this is the example I'm going with so what you have here now is and what seems to be and I get only read-only property in reality though that's not what you have if I open Ryder's il viewer and I build my project so it's building what I want to show you what it's doing here is by clicking that I can actually show the code the compiler will generate that's what we're taking a look at the intermediate language and I can show you that what will happen here is it will use the gate first name in the last gate name and the gate last name sorry and we'll concatenate it we'll use a string dot Concord method to create a string this because it's making behind the scenes is a method it property really is a couple of methods with a back packing field so we can actually quickly take a look at that as you can see the last name property has a gate last name and if the set last name is not there because it doesn't have a setter but if I go on at the very top at the very top story you can see that the last name has a backing field just like a normal field like actually let me just show with code private string first name same type of thing so like I was saying what happens here is this isn't really a property it's just a method that will be called every single time you're calling the full name property quote-unquote which means that the concatenation method in this string will be allocated every single time you call this method you don't really want to do that what you want to do instead is because this is based on read-only properties is you want to actually do that in the constructor and have the full name be computed once and then have a proper read-only string here and as you can see if I rebuild that with the code updated now the full name is a proper I get only fully named method with the Gator being give me the value of the backing field so now it has a proper backing field one before it was just a method computing a string every single time and then if I go in this code it's the same thing but concatenation is only happening once and then the value of the concatenation let me just make this a bit bigger and then the value of the concatenation is pushed into the backing field for full name and it only happens once now this might look very simpler you might say okay Nick this is not a big deal what happens it's just a string computation well actually these can be used the same expression body memories a feature can be used for pretty much anything and what you need to understand is if you do this whatever you have on the other end will be put in a method and effectively what you get out of this is this a method that returns whatever the body is pointing at so you need to understand that your recomputing that every single time and if it's a constant thing like a string it's probably fine but it can be anything and can't have computing it as well so you need to understand that this is how it will behave now last but certainly not least is understanding how enumerables work and how collections work and how lists work and how link plays into that so I'm going to go to this project and I'm going to show you the following code so what I have here is a benchmark runner we covered what benchmark dotnet is in a different video you can find it in the top right corner of your screen right now and then I have a class that I wanna test but all its really doing is it's creating a list with 10,000 new Goods and then I have two benchmarks one that checks the list dot any to check if there are any goods in the list and at least dot count more than zero so the outcome is effectively the same because it will tell me if I have at least one into my list but if I choose and actually let me just change to release because it needs to be released if I run this benchmark with the code one using link one not using link let's see what I get back in terms of performance so as you can see the test count the one that's just using count more than zero is actually significantly faster of course we're talking nanoseconds but that's besides the point it's significantly faster than the usage of link and that's because count actually knows the number before hand because it's effectively computed it's a list and the count is a property of the list while Amy being a link method you will need to go through the gate enumerator method and then use the move next to see if there is at least one element in the list now obviously you might say this is no biggie but here's where it becomes tricky you see this is a property but what happens if the list is not actually a list and I change this to I mean actually I can leave this as a as a list but what I can do instead is I can create a public eye enumerable good list date which returns the let's just return the list or not I'm gonna expand on it in a second and change that to this now as you can see count doesn't actually exist as a property anymore now count is gone and it's replaced with what is a method and the reason why that happens is because the ienumerable interface can be anything it can be a collection it can be a list it can be anything that can be enumerated so the interface itself doesn't know if the count is computed or not which means that if I click on that now this is turned into effectively what is linked and we'll do some checks to see what type of collection or list it might be to be more efficient but if it can't find any it will just go through the enumerator again now this will effectively perform in the exact same way almost if I run this so I'll spare you this execution but what I want to do instead is I'm going to return this I'm going to delete this actually and I'm gonna change it to forage list and I'm gonna say for each item in the list yield return the item and yield return makes this a true enumerable in a sense that it's not computed it's not backed up by the list data until this method is actually invoked which means that now check executing these two will actually perform different and let's just run them to show you what I mean now the test count run significantly slower than the NE the reason for that is actually pretty simple count will wait for all the iterations of this enumerable of yield return to actually be completed to get the exact count before it does the check on whether it's more than zero while Amy will only do it once to see if it has any element to move next so what you effectively need to understand and the reason why I am mentioning this is you need to understand how the difference between the method and the property works generally if count is a property and it's not a method it means that you can call it and it will be the fastest way to go about it and if you know that the bucking field is a list you don't have to use an enumerable just use a list unless you need it to be in innumerable in that case use an enumerable but beware that it might actually have a huge difference in performance as you can say depending on what it is so make this predictable by understanding what is backing up my data or what type of collection I'm using and what's the best way to do my check link can be very clean and pretty fast but it can actually be also a pitiful for your performance so be very careful when you use it it's very useful to decompile these codes and see how the work behind the scenes and things like benchmark dotnet make it very easy to test those methods that's all I had for this video five very simple tips that you can actually use to improve your code I hope you learned something you didn't know if you did leave a comment down below if I miss something you want to talk about it leave also a comment down below special effects my github sponsors for making these videos possible if you like what I do you want you can use a link in the description down below leave a like if you liked this video subscribe for more condom like this and we're gonna bail as well you can notified when I upload a new episode and we'll see you in the next video keep coding
Info
Channel: Nick Chapsas
Views: 50,439
Rating: undefined out of 5
Keywords: coding, asp.net, .netcore, dot net, core, C#, how to code, tutorial, asp.net core, javascript, csharp, rest api, development, software engineering, dev, microsoft, .net core, asp.net core 3, cqrs, mediatr, design patterns, clean architecture, clean code, asp.net core api, tips and tricks, 5 tips & tricks, tips and potential mistakes, dotnet, .net
Id: KirXASBYXUk
Channel Id: undefined
Length: 23min 57sec (1437 seconds)
Published: Thu Jul 02 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.