Let's Talk - Always use the "as" operator - No Thank you

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
sometimes i catch myself wondering why folks prefer using the as operator overcasting then i realize it makes them feel safer is it wise to pick safety over security safety or security [Music] what's up youtube welcome to this next episode on the let's talk series this one is about as the as operator versus the cast expression and i want to kind of set the record state with regards to some guidelines as it pertains to this as versus all the typical guideline is always used as i don't know if you guys heard this i've been in a few companies now but the coding standards were very specifically stating this aspect always used as and i believe um bill wagner's book i don't know the name of it but i think it's bill wagner but he mentions the same guideline and maybe it's all coming coming up from there i if i remember bill wagner's books this is from many many years ago so i don't actually remember the exact things but there's a few there's a series of some of these books or maybe just new versions you know new uh publications he mentioned the reason was you know it doesn't throw an exception as doesn't throw an exception while cast does and some performance benefit and all that so i'm not sure where or why exactly this guidance comes i think personally that this is a misguided guidance it's not practical it's not for the real world it's more like theoretical you know because throwing exceptions it must be safer and safety is not the same as security safety is about safeguarding yourself from unintended let's say attacks if you will attacks just kind of loosely you know attacks and that's honestly personal but some sort of intrusion some sort of a danger so it's an unintentional thing but a security is about an intentional thing as you know it's going to happen and you need to take measures these are security measures not safety measures safety is more like uh some of it is also emotional there's an emotional component to safety i think i'm not an expert in all this but i'm just thinking about certain times one would use safety versus security so you got a safety helmet that's as a protection in case something happens it's not expected to happen but in case it does whereas security is more of the intentional thing you know you know somebody's going to break into your house you know that somebody's going to do this since you have a security protocol and we have this in software as well right many uh software for automobiles and like spaceships these software go through much higher level of security analysis to ensure safety when it comes to the the code and the app and the application of the system is trying to operate on right so safety and security where safety is more to do with will the system behave correctly at the right time versus security is more to ensure that there are no issues calls that let's say at the memory allocation level or even from hacking perspective to ensure the system is always performing the way it's supposed to because those are intentional attacks if you will versus safety is more like a precautionary afterthought not necessarily afterthought but reactionary measure whereas uh security is more a proactive measure all right enough about safety and security um okay so the as operator and the the cost expression have been around for many many years i've actually used the as and is operators and cost expressions in other languages as well for example delphi has both as an is i don't know if c plus plus has that i don't think so anyway duffy has it and the behavior is the same and the guidance in delphi would have been the same so there's no real difference between c-sharp uh guidance if you will the way i would you know propose the guidance versus what i would say in delphi it's the same thing both the ad so the as expression will not uh take into account user-defined conversions while the cost expression will so that's a bit of a nuance in some ways i personally think that the fact that the as operator does not support user-defined conversions is a benefit you don't know what to use a defined conversion is okay good then you haven't missed anything [Music] if you haven't used user defined functions please don't it's not something that i would recommend at all it's like any other operator or loading uh you know even though the features there has been in there in c plus plus and c sharp i would never use that feature unless there's a quality thing going on regards to value semantics for reference types which by the way we'll get out of the box in c sharp nine with the record type so rather than you doing it let the kind of the compiler do that lowering compiler step kind of handle that aspect so that's more automated and it's kind of seamless but at the same time there are no chances of mistakes or misuse abuse with regards to the operator overloading or in this case user defined functions but nonetheless today's discussion makes a few assumptions which is you understand how the as operator works how the is operator works and how the cost expression works so this is not a video that's where i'm going to teach you how they work and you have a fairly good understanding of how they work for example the as operator will likely return a null in case the type cannot be converted to the type you asked it to whereas the cast will throw an exception right so that's not something i'm making you understand that the other thing i'm going to assume is given the core samples that i'm going to show you these are core samples that are kind of deeper in the cuts of the system than not had the entry points and so if you program like i do where you know we lock the front door and we lock the back door so you're safe in the house if you don't know what that means you can take a look at this video here and explain amongst many many other aspects locking the front door unlocking the back door so you're safe in the house it's assumed that this code is deeper in the system and so it's the parameters being sent to certain methods here are not null because they won't be they just never happen and so we don't have to ensure or check for null nullability as a result these are non-null reference types if you will right okay so let's look at the code there's two there's three code samples here fairly small i'm hoping they're pulled out of context so they are i'm hoping they don't lose the the value if you will because they pulled out from actual code so i'm hoping you're not thinking well i don't write code on that this is real code i see this a lot not just in my code but just generally i see this kind of code a lot and so i'm using it as a way to show you some common code that i see and how to fix that or what's wrong with them and then how to fix it so this is more like a core review thing so when i show you some code to look at it from the perspective of a code viewer what do you tell me to fix all right okay so and the third one is a valid use case for when to use the as or the is in this case specifically the is operator versus the cast expression all right okay let's get started okay so we have two separate methods here once they both got the same name one has a suffix of one and the other has a suffix of two very simple my employee type is the base class and both the software engineer and the accountant descend from the employee base type right the software engineer type has a role property that only the software engineer has and the accountant does not right so in other words they are in a hierarchy employee is an ancestor to software engineer and software engineer is the only one that has a role properly while the accountant type does not so what's what would you say is wrong with this code and what is what would you say is wrong with this code i'll let you pause here for a bit take your time and then once you've understood the code made notes whatever or you want to write a comment saying this is what i think it is fantastic write that there and then continue watching the video to hear what i have to say and if you have something different to say if you have a a bit of heartburn write me a comment let me know what your issues or what you think or why you're thinking a certain way so maybe you know you're going to teach me something or maybe i can explain maybe i'll not explain things correctly all right okay so the first question i'm going to ask you here is or i'm going to make a statement and ask a question both these methods do the same thing is it not they're doing the same thing but they're saying different things you get it the question you have to ask yourself is what is this code saying what is it telling me that's like the difference between um let's say body language and i'm not an expert in body language but i'll give you an example you could go research the web for sort of better ideas about what i'm saying but essentially it's like this let's say you know you're on my team and you say hey shiv you come up to me you know kind of by surprise and he says shiv you know this other design you gave me is uh you know it's not working the way it's supposed to work and i've got a better design you know than you propose i'd like to show you and i would say yeah sure you know let's see and when i do that i'm really being defensive i'm not open to your suggestion it's not always the case when somebody folds their hands i don't think if you come to my house and summer or winter you're gonna be folding your hands all the time it's cold i keep my house cold even in summers i like i like cold i don't like hot and so you'll be doing this all the time in my house so that doesn't mean that you're uncomfortable or you're being protective what i'm getting at is the code b could be doing one thing and it could be saying something else and programming with intent which is pretty much most of my channel i talk about these ideas programming the intent ideas you want to program to show me your intent in other words you are communicating as clearly as possible your intention by of writing code no comments just code your code should speak to me and explain or convey your intent so that when i look at this code later on while i'm doing a code review or 10 years from now i'm not wondering what you were thinking because you have communicated your intention really clearly so i'm not second guessing and if i know that's how you programmed then i'm in a much better place in the future either as my my future self or me as the person maintaining the code you wrote whatever that future is if i could just be assured that you programmed with intent then i never second guessed the code you wrote and i am better informed about how you were thinking what your intentions original intentions really were all right so these two pieces of code that do the same thing but what they're saying i'll give you a moment to a pause think about what i'm asking and see if you can answer that question and then i'll tell you the answer all right so let's go look at what i think these two pieces of code are saying okay let's look at this method first here now the first question the student programmers of you would say but shouldn't this employee be a software engineer both they just both of them just need to soften you know exactly so the first thing i would catch you without doing the code review would be why is that just not software engineer and if you don't have a good answer i'm going to say well then change it right because you don't want to assume from at the out of the external part in this case the method signature the public surface if you will you're saying i'm accepting of any software engineer but internally you're not sorry any employee but internally you're only accepting a software engineer but don't then don't kid anyone don't lie to me about saying that you want to do that genetically so don't try and build general generalized software unnecessarily if you need only software engineers to be here then fix the signature and the ambiguity is immediately eliminated all right get that okay however in this case that's not true in the sense that there are many times where you might need to have that employee as the method signature while internally you're only dealing with software engineer it's not uncommon because of probably sometimes polymorphism because the signature has to be such that it's working with all the indiana ancestry and sometimes like you know like say in events in gui applications sender and you know object so it's always going to be object right and sender it's such a high level abstraction that anything can come through and it has to be because any event can be sending you any object it could be a button or a text box or or a form or whatever right so in this case let's assume that the employee is the right signature of the method we're looking at the implementation all right but if you didn't catch that employee aspect then you need to sort of rethink your code view strategy you should be looking for those kind of things all right so this i'm going to tell you what i think this code is saying this is what this code is saying this code is saying well i i can get an employee so i'm not quite sure that every parameter that comes in here is a software engineer so i'm going to use the as operator and i'm going to assign the as cost the converted version of that to this variable software engineer and yes i understand it'll be null but i'm going to of course call into the role method the role property of the software that will work and yeah there's an issue here with regards to the null check not taken now this is very common i see this all the time and really this is a symptom for the another problem but i'm going to get to that later i understand there should have been a null check but you will see you can look at your code currently your code base you'll find that many times you'll use the as operator but not to use a null check afterwards and that's indicative of a different scenario which i'm going to get to all right so this is saying you're not sure right however by not doing a null check here you're actually confusing me you're saying okay on the one end you're not sure that this is going to the employee is always going to be a software engineer yet you never check for a null so you're going to get a null reference exception here i'm not sure i did was that intentional or are you really telling me that you know this employer is always going to be a software you know you see the confusion you write code like this is your intention is not clear now i'm confused like if i look at this code as somebody who's maintaining the system or doing a code review i'm not quite sure what you mean what are you saying when you write code like that let's look at this this code actually won't scroll up and down it just becomes difficult to okay this code is saying well this employee just has to be a software engineer just using the cost expression or what i call a hard cast as and there's no it bloody will work on yeah else is going to throw an exception and it's going to be assigned here and immediately i just go for all in other words it will never come to this line and throw another reference exception however it could throw a typecast exception on this line right safety versus security which do you prefer the first one where you could potentially get another reference exception or the second one where you could get a typecast exception okay i'll tell you the type cost is way better that normal reference is going to be useless to me i don't know what that would mean the type car is going to very clearly tell me that's a problem now the question really is when that occurs even if it's a non-reference exception when that occurs what's the solution what's the fix most of us are going to be will jump to fixing the problem where you find the symptom which is you know on that line where it throws the exception oh it says no reference okay and you just need to check to see if it's not null you are now creating a false sense of security and that's the problem you think you're being cautious you're securing yourself from a potential attack but effectively you you've hidden the problem the problem is still there you just evaded the problem so you said it's not my issue i'm not gonna deal with it and let somebody else deal with it never treat the never trying to find a solution by treating the symptom try and find the solution by finding the root cause and then finding a proper solution that prevents the problem from occurring at the root itself rather than fixing or treating the symptom makes sense the casting the second method the casting option is saying very clearly the code is saying i'm not expecting this to be nothing but a software engineer so if it's not a software engineer and you get a typecast except caller you fixed your you fix your problem i'm not going to fix it i'm doing my code just fine i'm expecting only a software engineer at this point in time in my code right that's a valid assumption to me you can validate intended intention to show again the symptom is not where you fix the problem you'll see the typecast exception happening in the second method but the solution may be to fix it in the somewhere of the call chain how did a non-software engineer instance come down here because this code is very specifically made for a software engineer i hope that makes sense right so sometimes being not only st all the time this is i've learned this the hard way many years ago when i started programming i was scared of exceptions i mean exceptions were like my nightmare right aren't they like oh my gosh another exception or in those days you know gui applications they would just crash and so everyone was petrified of exceptions including myself so my whole all the code i wrote was in this preventative defensive mechanism of trying to defend against an exception like being defensive i don't want to see an exception without i mean today i'm smarter in those days i wasn't so what i'm getting at is being scared of exceptions is the wrong thing you need to embrace exceptions exceptions are there to help you okay they're giving you an early warning signal about something going wrong right the problem is when people start to get scared of exceptions they put try catches and try to do whatever they can to evade or avoid exceptions and i believe the guidance on as you know always use as when you want to do a cost or conversion instead of the cost expression i think comes from that style of thinking and because i don't think in that way i think the better option is to let the exception occur because the the statement is clear let's try and fix this let's say you say okay well she wanna just put a null you know check over here we say okay let's do that so if software engineer is not equal to null right then let's do that and then what what's the else about where's the else what do you do in the else and you could say yeah well there's nothing to do and that's quite possible in some cases i'm not saying that's not a scenario but that's not generally the expected scenario okay the times i've seen this problem is when the else should never have occurred to start with you understand so that's when you want to say let's use the cost expression rather than the as operator right so this is the correct solution and this is not because you're hiding the problem yes it won't throw an exception you only come in here if it's not null but when it's not what happens it's like a sanity just pass through it's like the guy that doesn't have a badge to enter your uh office just walks through the back door and is in that's not what the intention was of security the security was to make sure that everyone comes to the gate and only those who have the badge can come through the door you want a back door right all right so let's look at the second code base second code solution okay i've got two of these i'm going to show you both should i let me show you how this code would be used right so let me fix that the main method i'm going to just comment out this code and write out some new code here all right so the idea is we have the genre enum let me show you that and let me close this a little bit okay so every enum element has an attribute associated to it and the attribute can be sort of the description if you know many times where the nums can only be one words like a c type name while the description could probably be multiple words or spaces in it and so you want to have the cnn that tells you what the human readable form is for example like psi dash 5 versus sci-fi which is how you can specify the enum element here or the field if you will these are called enum fields so the program cs is essentially getting the collection of enum fields and that's the field infos the field info is the collection the runtime metadata of every one of these uh genre fields right the one that i showed you earlier these ones though this over here so there's a collection of each of these but inclusive of the the metadata so the attributes that come along for the right all right that's what the field infos is and then we're calling a method that says initialize it should have been initialized genre to description mappings and that's what i'm showing you here let me also open up the parser 2 and split that horizontally okay and let me see and just squeeze this up a little bit align it so you can see the full method body for both of these methods all right one more okay that's it this is the fold you can see that it close here close quality here all right so pause the video see if you can determine which one is the better one or the right one on the other way to do it and then i'll continue on all right okay so this is the how was the original code and we are working that in a description attribute here and this is the standard method in dotnet's reflection namespace we can ask it for the the type of the type you want and then it's going to get you the custom attributes of that type and then there over here is using an as to convert that result it comes back as an object array the idea is to cast that to an enum description attribute array all right so what this is then is of type enum description attribute let me see that again zoom that in can you see that okay okay so the there are a few problems here if you haven't noticed them or haven't picked them out pause and then i'll then continue on i'm going to start telling you what the issues are and why what my reasoning is and then the solution which is the one on the top and why that's the better solution all right so the first problem is that if you ask this method to get this type then it can't be any other type using an as doesn't make sense you're again confusing me are you saying that even though you're asking it to get you this type of attribute it could be something else so you're hoping for the best you know you're playing it safe or can you not just cast it right so that's the cost over here so we are casting it over here this is using the ads all right the second thing is a guidance from from.net the guidance goes like this if a method returns a collection of some sort enumerator sorry innumerable array what have you if a method returns the collection that method should never return a null all right and the bcl the base class library the.net c teams library if you will uses that guidance so their methods will never return a null if they return a collection they'll be empty collections but not a null connection all right so right away you can see that this condition will now be met which means this code can now be tested code like this this branch if you will of the conditional will now be tested and so you've got some piece of code that you never test and yet you want to put in there so it doesn't make sense right so you can take that out now if the collection is what's returned here is an empty collection then the for each over here down here will just be skipped anyways and so now you have the other the soul condition this whole thing doesn't need to be there in the first place right and so you have the solution here now there is a nuance here where it's checking for the length is equal to zero so continue because here we're not doing it doesn't check so of course if the collection is empty it implies that in this case the attribute there is no attribute associated to that field in the in the enum right now in this particular case that's the requirement the requirement is if you have an enum then every element field in that enum needs to have the attribute declared on it irrespective of whether the description is the same as the enum or not so as a result having a lynch or not having a length check is a valid scenario in this case but if you had a different way of doing things then you could say well then that case we want to check the length zero so i mean you still have to the idea is in this specific case it sort of makes makes it easier to not have the length check and have the rule that says that every field enum field should have an attribute associated to that because the logic gets a little more complicated if you understand what the actual code is doing but for this purpose so for the purposes of this discussion just assume that the line check is not always required it's not wrong but again only use it if it makes sense right because again if you don't use a length check here and it blows out with the length of zero right what are you saying well again the problem is not here the problem is that you need to go back to the enum and decorate that enum with the attribute right don't fix it here by trying to be safe again so you know be aware of that all right hopefully these two examples which are very very very common have made sense to you and now we're going to go on to the third example final example where i'm going to show you or make a case for when you should use the is or the as operators when is it right to do that right okay this code is available on my github repo i'll put a link to the entire solution in the description below but this specific file is the exception to http translator class you can look for that the idea is that this class's purpose or responsibility is to take a c-sharp.net exception and translate that to http which would mean of course if it's an exception then the status quo might have to be changed to a 400 or some series of 400 or some series of 500 right and you might want to have to take that the message of the exception and put it in the http context or the content if you will of the body in the http protocol and in my case i also set up a header that gives me the type of exception that occurred on the server side right because sometimes the client side which is also an internal service might have to rehydrate an exception of the same type and throw it so in this particular case it's doing three things we're setting the status code appropriately which is the main logic here that i want to show you like what should the status code be it's also setting the header with the and the reason phrase right so let's take a look at that so setting the header so this is the entry point the public method that's private so you can't get to this you know directly you have to call the static public starting method here providing it with an exception in this case again the exception base class is a requirement because any and all exceptions that occur in your system will come through here so there's no way to find tune that further or confine it further to our specific specialized kind of exception right so the header we're going to just say exception type header and it's going to be the type name of the whatever the exception is so that's irrespective of what the exception type is now this reason phrase property which is available um in our exceptions by our i mean the system is the movie service system and so there is a base exception called movie service base exception so all our exceptions not non.net exceptions all our exceptions descend from that base so the dotnet exception is up here the root exception the systems exception descends from that directly and then all of these systems exceptions distant from here not from there not from the darknet exception they all the same from here in this case is called the movie movie service base exception right and from that movie so space exception there are there are two kind of branch technical base and business base so essentially we have technical exceptions and business exceptions that both descend from our movie service base exception all right and then the business exceptions will be like a horizontal a lot of broader sort of descendant uh tree not deep and the same technical they kind of be from that point forward it's kind of flat right it's not just not going deeper hopefully that makes sense because it's going to be you're going to need to understand that to look at the rest of the code so what we're saying here is that the movie service base if this exception is so we don't know so we can't be sure and if it's only if it is do we want to do something but you could use as in some situation in this case i don't need an s i just need an is so in this case this is using the the new c sharp pattern matching uh feature in c sharp seven i think it was it's kind of like a as actually i'll explain to you if you don't know the syntax you look at that it's saying if exception is this this is the type declaration that's the variable declaration if the condition is true this variable will hold a reference to a movie subspace in other words it has cast this exp exception to that all in one breath so it's kind of like a as operator with a null check built in right so even though you're seeing it as it is it's actually it's an as from non expression matching if you will syntax makes sense all right and so we're saying if the exception is one of our exceptions then all our exceptions have a reason phrase exception or even a reason property so set the reason phrase http header to that but it's only available on our exceptions therefore you can only do this minus one of our exceptions right so we need to ensure or check that between the sony if it's one of our exceptions right now it comes to setting the status code we have another method here and this again is for all exceptions right now you one could say you could optimize it by saying okay you know the status code but this is the base class so the the status quo for business exceptions could be of like a 400 series technical exceptions could be like a 500 series you don't quite know yet and in this case we only know that it's the base class we don't yet know there's the a technical our business exception one of our technical or business exceptions so we couldn't optimize too much here so it's basically being done over here once and for all for all exceptions we send that exception to this method here so again this signature says i need an exception type and it says well if it's a movie service not found base exception let's say business exception not found it returns a 404 but if it's just a movie service business based exception then it's a forum in other words they're saying for all business base exceptions and descendants our response status score should be a 400 unless the it's a not found business exception it's a 404 and for all other exceptions the status quo should be a 500 which is all of our technical exceptions and every dotnet exception is considered technical of 500 right hopefully that makes sense but this is probably the only time and in fact for the most part i don't know for how many years now this probably the only time i actually use the is or as is combination of operators most times i use a cast right so hopefully this is making a lot of sense hopefully these examples have made sense as well even though i've kind of pulled them out from their name main systems the main code you might think that is a bit not quite engrossing the example but i'm hoping i did a good job alright so this brings me to the end of this video i hope you've learned a few things i hope you've enjoyed yourselves if you have please give me a thumbs up and i will see you next time you
Info
Channel: Shiv Kumar
Views: 984
Rating: undefined out of 5
Keywords: C#, .NET, OOD, OOP, .NET Core, ASP.NET, ASP.NET Core, Programming with Intent, Code Reviews, Code Reviewer, cast expression, as operator, cast vs as, as vs cast, explicit conversion, implicit conversion, user defined conversions
Id: buUVmKAFiFo
Channel Id: undefined
Length: 35min 19sec (2119 seconds)
Published: Sun Jan 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.