The .NET on AWS Show, featuring Maarten Balliauw!
In this episode we are joined by Jet Brains Developer Advocate, Maarten Balliauw! Join us as we dive into Nullable Reference Types in C#.
Brandon Minnick
Amazon Employee
Published Jul 15, 2024
Continue to The .NET on AWS Show, featuring Diana Pham
Loading...
Brandon Minnick 1:06
Hello, everybody, and welcome back to another episode of the dotnet on AWS show. As always, I'm your host, Brandon Minnick. And with me this week, we have an amazing new guest, co host. Jose, Jose, welcome to the show.
Jose Yapur 1:23
Thank you. Thank you for inviting me. And hopefully, Francoise is going to be ups in the next one. So I can be all the programs with you. And sharing. I love that. So it's a great opportunity to share with with the people and thank you for inviting me.
Brandon Minnick 1:40
Yeah, we're so happy to have you, Jose. And for folks who maybe have never met you before who are in what do you do? Well,
Jose Yapur 1:47
I'm developer advocate. And at Amazon Web Services, I'm based in Latin America, especially specifically in Peru in Lima. I work with dotnet and containers and Gen AI. We're for some time now. And I really love to share dotnet stuff. It's my favorite programming language and framework, together with C sharp. So I think it's a great opportunity with a great community. And we have a bunch of stories to share with all the people on how can you be like a great developer using dotnet and also AWS. So love to be here. Yeah,
Brandon Minnick 2:30
and thanks so much for for joining us, Francois out. He's on tour. He's speaking at a conference this week, couldn't make it. And hopefully we'll be seeing lots more from Jose in the future as the fills in for for me and Francois, as necessary. But yeah, thanks so much for joining. And we were talking about the rundown. Before the show, we're hanging out backstage, and we're saying we always have a couple of announcements that will share the beginning of the show before we bring in our amazing guests this week. And and Jose, you brought up a really cool tool called cue cloud. Oh, hon. QC to you cloud transformation in dotnet. Hopefully, I got the acronyms. Right. But it's not out yet. It's coming soon. But what is this? And what can we expect? Yeah,
Jose Yapur 3:23
actually, as you said, this is not out yet. But it's amazing how fast you can migrate. For example, for an older dotnet framework to the new ones, I know that you have been there TGS release released software piece. And then you figure that next week is releasing the new version, right. And you have to make changes. And sometimes it's not, they're not obvious, right? So you have to read a little bit about the recommendation and some things that you have to change on your code. If you have, like, loose if you have like really tight dependencies, or maybe the other libraries are also tighter. So you're seeing brown engineering, with you the inside inside Visual Studio to make those bold transformations, just with a brown without doing that much. It's amazing. It worked for me, I made three the 3.5 dotnet 3.5, to the latest version, and it was pretty easy. It took me like 10 minutes in total. It was an older project that I left for years now. But it work. And the other thing is that now, I also checked, I haven't tried it completely. But I also checked that when you have some hard coded for example, directories tied to Windows and you need to migrate the application to or even processes. I need you you need to migrate that application to Linux for example. The code transformation will help you with that as well. So So the future is it's glowing, hopefully it's going to be available for for everyone present. And you can try it on your own and see how it works in your own in your own personal experience. Yeah. And
Brandon Minnick 5:15
that's, you know, we were joking before the show, because obviously, it hasn't been released yet. I think we're targeting next month for private or public preview of the code transformation tool. But yeah, we were joking before the show. And I mentioned that I'd seen some demos of it internally. And anytime you see, like a product manager demo something or like, okay, yeah, that's cool. But like, does it actually work? And and Jose, yeah, you coming in telling me this morning that you're like, Yeah, I took a dotnet framework 3.5 project and ported it to assume dotnet. Eight, using this tool, and it works. That's like, Oh, wow. Okay. I guess this AI stuff really is the future. Hmm.
Jose Yapur 5:59
Yeah, yeah, it is. And it's Carson time, too. We were joking about this, also, that it's hard to figure if we are able or not to talk about some stuff, because we have some early access to the projects and the services, right. So we are not sure if they are coming out or not, or are falling. So it's kind of messy, but it's a lot of fun. I
Brandon Minnick 6:26
said, it's not out yet. Can we talk about it? We talked about it anyways. Well. So yeah, everybody keep an eye out for the code transformation tool. It'll be coming to the AWS toolkit plugin in Visual Studio, and also JetBrains rider. But speaking to JetBrains. We have such an amazing guests this week. We are joined this week by Martin value, who is a developer advocate at JetBrains. You've seen him at conferences as a speaker all around the world. He's here to talk about all the things in dotnet with us today. Martin, welcome to the show.
Speaker 1 7:08
Thanks, Brandon. Thanks, Jose, for having me. This is this is cool. I've never been on this show. So thanks.
Brandon Minnick 7:14
Yeah, we appreciate you coming on. So Martin, for folks who haven't met yet who are in what do you do?
Speaker 1 7:22
I'm a developer advocate at JetBrains. So what I do is speaking, I do blogging, I write documentation. I talk with people in a team about what I should be talking about to developers out there, but also to developers out there to talk about what we should be building in the themes. My main interests are really in everything C sharps about language, but also things like performance, and so on. And I've been on on the clouds while at least on HTTP for a long, long time so far. And everything that is that is cloud related is also in my in my field of interests.
Brandon Minnick 7:58
Gotta love that. Yeah, we appreciate you joining us. Like I said, I've I've seen you, Martin, all around the world at different conferences. So super excited to have you join us today. Now there, there is one question, we love to ask everybody who joins us on the show, because we also love dotnet. And it's so fun to learn everybody's origin stories. So I'm curious, how how did you get back in? Or how did you get into dotnet? Back in the day,
Maarten Balliauw 8:24
this is a, I'm gonna say by accident, really, because it was by accident. So when when I was just out of school, I was applying for a job at a consulting firm, and they had this new employee thing where they would stay consumers and everything, and you would get five or six weeks of training, and then off, you go to customers and so on. But the day that I entered that company, they had a questionnaire with two questions. One of them was Do you what programming language do you do? And what programming language would you like to do? And based on that you would do a test and then you would get into whatever you want to do in at that at that company. And because the last project that I had in school was in dotnet. I thought, well, let's take the easy way out. And I'm just gonna say dotnet all the way. And this is how I ended up doing not net.
Brandon Minnick 9:16
Wow, to you almost literally just fell into it. Yeah, exactly. Have you even done anything with C sharp at that point? Or is just like, Yeah, I think I could do this. It sounds cool. school
Speaker 1 9:30
projects, mostly. So back in school, we got Java and we got dotnet. And I think the last thing was something like a course registration system that we built in ASP. Net 1.1 I think back then, so web forms and everything. And that was all still fresh in my mind. So I thought okay, let's let's go with that because Java that's been two or three semesters, so that's not as fresh in mind. So that's why I'm in dotnet. I could have I could have been doing Java
Brandon Minnick 9:59
in how A sad we'd all be if you were still doing Java.
Maarten Balliauw 10:05
We'll never know we'll never know maybe in a parallel universe or something, but we'll never know
Brandon Minnick 10:09
that somewhere out there. There's a planet Martin, right and Java, but not on this one. We're here talking dotnet. We're talking C sharp today. So, Martin, were mentioned earlier that you work at JetBrains. What? What, what is JetBrains? It's a, it's a funny name, right?
Maarten Balliauw 10:31
Yep. I have no idea. So this is a question that I've been asking myself as well, like, Where does the name come from, but it is what it is, right? So we need to be more productive and better at writing your codes and doing all of the tests that typically are there around programming in any language. So we have writer and Resharper for dotnet developers, but there's also IntelliJ for Java, which, ironically, back in school there. I also started with IntelliJ. I think version one or two, it was back then. So I've, my first IDE that I tried was actually JetBrains. We have IDs for pretty much any language we have. Ai assistant, we have c ICD, so lots of different services. But our core focus is on MIT's
Brandon Minnick 11:18
Yeah, I will say it myself. So I, my origin story goes back to working at Xamarin, back in the day got acquired by Microsoft, I was at Microsoft for seven or eight years before jumping over to AWS. But starting at Xamarin, we had this IDE called Xamarin Studio. And then we got acquired by Microsoft. And some was a genius in air quotes here, marketing person, and Microsoft was like, wait a minute, you guys have an IDE that runs C sharp code on a Mac, we should rebrand that to Visual Studio for Mac. And all of us are like, whoa, like, don't do that. Because it only works for Xamarin. And the minute you call a Visual Studio, people are going to expect it to be the same as Visual Studio on the PC. And they listen to us. No, they did it anyways. And just bout a year ago, I think they are Microsoft announced that they're sunsetting Visual Studio for Mac. And so this idea I've been using myself on the Mac, for almost a decade now is gone. And so I've jumped over the rider and I have no complaints. You know, it took me like things are in a different place. So I had to figure out where like the new buttons are. But yeah, here too. I love it. I I find more and rider, I assume thanks to Resharper and all the recommendations you have that? Yeah, I find more performance improvements and fixes like that in writer than I ever do in or did in Visual Studio. So I'm a big fan. I love writer highly recommended,
Maarten Balliauw 12:58
of course a bit biased, but I also like writer a lot, especially since I'm I am working on Windows and on Mac, and I just have the exact same ID on all of my devices, which is, which is a godsend in itself.
Brandon Minnick 13:11
Absolutely. How would you Jose, what are you using to develop these days?
Jose Yapur 13:18
Actually, you know, I want to go back as well, because everyone shared with their start with with dotnet. So I started on school when I was in high school, developing with Visual Basic first, it was a computing class. And then when I joined the University University was pretty much Java all the time. So when I get out of the university, I decided to stop doing Java. I was I was I was tasked with that at that time. And I figured that that was going really good. And something called C sharp was was there. So in C Sharp was something like that Java, but better for me at that time. Right. So I started with that. And, and then also I started with Windows apps and stuff and I worked for Microsoft for even more than 10 years actually working with with dotnet and some of the other stuff. I also work with we get brains. I actually, you know Martin and Brandon something that I didn't like in the past was the learning curve of how are we having two different IDs with with the same brand. So I really do the same stuff in Mac and Windows right so it was hard for me to make that transition. And when I joined AWS and I have a Mac I was expecting it was actually I call your your remember for for a project that we have internally and you you show me how to install Visual Studio Mac right because you know I still use it. So, yeah. So having like the same ID on both platforms and having the same experience, it was pretty good for me. So what I'm doing right now, for example, is I'm creating a beautiful system on dotnet that is willing to replace a community program manager from my team virtually using DNA. I'm just kidding. But it's going to impersonate some people to be faster with communities and having my work Mac and my personal Windows laptop with the same ID it is great. I really love.
Brandon Minnick 15:42
Yeah, that's a really great point, I feel a little bit attacked, because I still use Visual Studio on the PC. And now I'm kind of wondering why. Because yeah, like our iOS toolkit works with writer. So I don't know, maybe I'll make the jump. I've been, I guess, so used to using two different IDs between Windows and Mac for like, like the last 10 years? That I've never thought about it before. But yeah, you guys are right, it just,
Maarten Balliauw 16:13
it was also really funny how muscle memory goes. So we also have IntelliJ, which, which is our Java IDE, which is exactly the same look and feel just a different, different type of programming language and ecosystem around it. And weirdly enough, my mind does not parse the difference in shortcuts between writer and IntelliJ. Or at least it did notice that there's a difference for those between those. And while we have key maps that are common across all of the IDs, my brain does, it refuses to use the same key map in both areas. So I have made in my my writer brain, it's weird.
Brandon Minnick 16:50
Yep, I know what you mean, I've been I've been brought some keyboard shortcuts into Ryder, from Visual Studio for Mac that are just like, so deeply hard coded down here that you don't even think about it, like code formatting in Visual Studio for Mac was control i. And I found like, I just hit that out of muscle memory now like I don't even think about it. Like as soon as I write some code, format it boom. And then I went to do it and writer and it just didn't work. I was like, Nope, we're just gonna change this. Or not learning something new here. But speaking of learning new stuff, Martin, were chatting before the show, and we're talking about nullability nobility in C Sharp and the best ways to do it. You're an expert on it. So how what, what is this? And what do we do?
Speaker 1 17:43
Really good question. So I think nullability was introduced back in C Sharp, eight or nine. So it's been there for quite a number of years. And the idea of nullability in C Sharp was to give you some information about when a reference type could be null and when it could not be null. So to essentially help you with knowing when you should be doing a null check, and to avoid null reference exceptions. Now, the interesting thing is that ever since nullability, has been enabled by default, I think in many projects, and a lot of us are probably using it without even knowing that we're using it, which probably added question marks and exclamation marks all over the place. There's actually really, really additional useful things in this nullable reference types feature that C sharp comes with. So my my main mission of the day, and pretty much of a lot of conference talks that I do as well, is to make people aware that there's more stuff than just an exclamation mark and a question mark, and that you can really have codes that tells your developers or anyone consuming downstream dependencies that you were writing, you can communicate where you expect no, to be possible, and we're not.
Brandon Minnick 18:53
I love it. Let's, let's jump into it. Should we bring up your screen? Yeah,
Maarten Balliauw 18:57
let's bring up the screen. And and let's, let's try and describe. So I have a very, very simple example here on screen, which is a method called without nullable reference types, where I'm doing a couple of things, I have a method called get value, which has a signature returns a string. In fact, it does return null. So the code reads that I'm returning null in this case. So when you would call get value even though it says that it would return a string, it's actually returning null in this case. So if you call that methods and assign anything to a variable, say String s, what will happen when you do a console dot write line of s dot lengths. Anyone want to take a guess exception, or reference exception? Exactly. Because you have this null value or there's no reference. And you're requesting it's to give you back the links and of course, there is no variable to give you back the link. So this will blow up and nothing will happen. Or at least no reference exception will happen. Your code may crash and things make ourselves Now with nullable reference types, you will see that you can write essentially the same codes. But when you enable nullable reference types, and again lately is it is enabled by defaults, your get value methods can instead of just returning a string, it can now return a nullable string, which is written as a string question mark saying that look, this string is annotated that it can be nullable. When you call that exact same methods in the exact same code sample, where you call in to get value that returns this nullable string, and you assign it into a variable named s. And again, you do a console dot write line of s dot length, what will happen?
Brandon Minnick 20:38
No reference exception.
Maarten Balliauw 20:40
No reference exception is correct. The main difference if you if you look on screen here, the main difference between two the two variants of the codes is that by adding this nullable annotation by adding this question mark, you get some hints when compiling and when writing code, the IDE will give you some information saying look, this get value methods is actually converting a null literal or potentially null value into a non nullable type in this code, are you sure you want to do this? So nullable reference types don't give you runtime safety, when you run the scouts, it will still throw a null reference exception. But you get this compile time and design time, information about whether something can be null or nuts. And based on that you can do things like for example, add an old check there. And if your ID is smart enough, which alternate IDs are, you can either change the type of actually also being nullable, or do a null check or do this bad, bad thing. And I will keep hammering on that. That you can suppress this nullable warning with an exclamation mark. But ideally, you just want to either throw an exception or use a fallback value. For example, you say okay, string notes empty is the default that I'll use if null is returned from this get value methods.
Brandon Minnick 21:54
Very nice. Yeah, I will say, I, I love this feature. I love that it got added to C sharp. And I'll also say I totally understand why the C sharp team didn't. They, they allow us to opt into it. So like you were saying earlier, it's enabled by default. But really, it's just it's enabled by default in new projects. Like if you do like a file, new project using the templates. That's when unknowability is turned on by default. But if if you have an old project like Jose was talking about is dotnet, framework 3.5 project. It's not gonna be enabled by default. And I know they did x, I didn't want to break anybody's existing code. But I love this so much, because it prevents those runtime or helps you helps you prevent those runtime crashes. Like you said, they can still happen if we write bad code. But yeah, I hope someday in the future that this is enabled by default. And what I do in my projects is I'll say warnings as errors in my CS, CS proj. file, you can say where to get errors and pass in no nullable. And then that'll ask or, basically, yeah, escalate everything from instead of just being a warning, like right now Martin can build this code, he can run this code, everything will run bla, actually, you fix the null reference exception already. I see. But before you fix, we move. There we go. Yeah, like we have, we have like yellow squiggles, little warnings that, you know, any good C sharp developer ignores those yellow squiggles, right? Those ignores those warnings in the compiler output. But yeah, if you say, warnings as errors, nullable in your C sharp project, then you can get those bumped up to actual compile time errors. So your your code doesn't even build. But I might be getting ahead of myself here. But what are we doing?
Maarten Balliauw 23:57
Just want to go quickly into one of the things that you mentioned, like if you're using older dotnet framework versions, for example, that don't support nullability in C Sharp, and there's actually I'll share it for the show notes. There's a polyfill library made by Simon crop. And he's essentially shipping all of the necessary attributes that have to be compiled into your assembly to make use of nullable reference types. If you are using any older version, then that's fine, those attributes will just be there you will get no benefits or whatsoever but it will still work. If you are a new version of dotnet and especially C sharp because this is C sharp feature you will see that everything lights up and you can start using nullable reference types there. So really cool library and really cool guy as well, Simon,
Brandon Minnick 24:41
I didn't know that existed. How how's that working? Is it just bumping up the default language?
Maarten Balliauw 24:51
No. So what happens when you can bail with nullable reference types and actually this is this is going completely off the rails but this is cool and effortless. If you look at the IRL viewer in, in writer here, I of course have to typewriter has a built in viewer, I actually show a hell, you can show low level C sharp if you want to see like the flattened version of what happens with interpolated strings, for example, or the high level C sharp, where you see the nice version of how things work. But anyway, if you look at the intermediate language version, you will see that when you enable nullable reference types, that at some points, where are we should be in there somewhere for my get value methods. It's not being at it, I should probably recompile. That's, that's the reason in between the runs. If we did it still had the old code there. But you will see that at some points, there's going to be a nullable attribute in there. Okay, let's find my getValue methods. This is our demos go right? Yes, there we go. So there's a nullable context attributes that essentially highlights how the compiler should read these methods based on nullability. So what it looks for is the value of the nullable nullable context attribute that is there. So based on the least amount of added attributes in there, the compiler doesn't shop and either says, Look, everything in this method is by default, annotated, which means it can be No, or it's not annotated, which means it cannot be no, like, no question mark means it cannot be alright. So those attributes are there for the compiler to work with. If you ship your own libraries, you can have those attributes in the intermediate language there. And the compiler will also know when you are using that third party codes, whether something can be nullable, or not. The package that Simon has, it essentially injects those attributes, so that the compiler on your machine where you're authoring this library, can still emit those attributes, the consumer will still see that those attributes are present. So the IL will not fail when you open it up in a new process. But just not not give you the information in the ID at that point.
Brandon Minnick 27:12
That's incredible. That's right. And by the way, wow.
Maarten Balliauw 27:17
Simon has more things in there. Because there's a lot of language features that have this attribute based way of working. And the essentially as a couple of those for pretty much every feature in the in the latest five or six C sharp versions.
Brandon Minnick 27:32
Holy crap. So who are how do I know if this is for me? Right? Because what did nobody came out with C sharp? Eight, which is that think
Maarten Balliauw 27:43
it was eight? Yeah. Three,
Brandon Minnick 27:45
Data Core three. So obviously, we're using dotnet. framework, add in polyfill. It'll make your life better. Where Yeah, where was that cut off for knowability.
Maarten Balliauw 27:59
I think it was nothing, that's true, or something. C sharp enforcing sharp, nine, C sharp eight, I think even. It's really cool. Like, if you use anything newer, you will get the nullability feature. But if you install this polyfill you can also use the code that you might compile on a newer runtime, it will still or on the newer SDK, it will still work with with the older runtimes.
Brandon Minnick 28:24
Very cool. Very cool. Yeah.
Maarten Balliauw 28:29
Cool. So my mission of today is not to talk about just adding a question mark or suppressing things with exclamation mark, my actual mission is to show you what else you can do. And so I'm going to bring up another example that I have here. And that is in annotating codes. Yes, this is the one. So what I have here is a method called slug phi. And my slug of phi method is making use of nullability. Like I'm seeing that the slug of phi method will return a nullable string. So it can be null when you get a return value. And it takes one parameter which is value, which can also be nullable. What the slug of phi method does is if the parameter is null, it simply returns null. If it's not null, it will look at the value and create a slug out of it. Like if you do a blog post, for example, you would write the title this one would replace all the spaces with a dash, and then return a lowercase version that you can use as a URL. very naive implementation, don't call using this one. But just to have some example. Now there's a couple of problems with this one. If you use this slider, find methods and you pass in null, you will indeed see that's the return value there is marked as this is going to return a null value, it's going to return a nullable string in this case when you pass in null, but also when I pass in an actual value like this is fine or whatever I want to put in there in terms of the title. You will see that the compiler and the IDE will still see that this slug of phi method will return a nullable string Oh, which is probably not what you want to do. You somehow may want to communicate, that's when I pass no, then I'm going to get back a nullable string. When I don't pass null, I want to know that the string is never going to be No, I shouldn't be doing null checks, none of those things. So how would you go about that? Well, turns out, there's more attributes in this nullability feature than you thought there were. There's an attribute called No, if not No. A very, very strange name for an attributes. But what that one does is essentially say, look, the return value of this methods will not be know, if the parameter that I'm naming here value is also not no. So it's essentially like my check that I do in the code there, which runs at runtime. This is a compile time metadata thing where I say, Look, if there's a non null value passed in, it's going to return an unknown value as well. And by doing that, you immediately see that in the IDE, this lights up as my null value that I pass in this, like if a method is returning null, or a nullable string, but when I pass in an actual value, it is returning a non nullable string in this case, so this is really cool. And it helps me communicate as a library altar to consumers of my slugger fi methods that depending on which arguments they pass in, that the value or the results might be different. And that you don't need to know check in this case.
Brandon Minnick 31:27
Yeah, yeah, these are really cool. Because this to me demystifies, how kind of the notability and dotnet works, because, you know, there's, there's, if you've ever used, if you ever turned on notability, or you just did a file, new templates, it was turned on automatically for you, you've probably noticed, you can do things like if you say if string.is null or empty, passing the string. And if that's true or false, depending on the result of that, like if this, if we already proved that the strings not know, then it's like somehow C sharp JetBrains Visual Studio knows that the rest of that code does not have a null string. And I always thought that was like, I was like, this is super cool. Like, some really smart person figured it out. And yeah, it wasn't until I learned about these attributes. So it's like, Oh, is that what they're doing? So did the dotnet team go through and add all of these attributes to all of the code in the dotnet, PCL,
Maarten Balliauw 32:33
they have done exactly that. So if you write a string that is null or empty, and you can Control click and navigate to that is null or empty methods, you will find in the sources of the nets, if I can find them, taking longer than expected, but you will find those attributes there. So dotnet team, I think it was probably dot nets, six, where all of the BCL was annotated with those attributes. But in the case of string that is null or empty, for example, you will see that there's another attribute there, which reads a bit backwards if you think about it. But what it does, what it does is essentially say, Look, if the return value of is null or empty, is false, then my value that I pass in is going to be non null. It's very backwards. If you want to write this, this thing for yourself, essentially, you would want to say, Okay, if value is null, then this is going to return false. So this is the other way around. But it's just faster for the compiler to essentially read this attribute and do something with it in terms of the flow analysis status when you're writing codes.
Brandon Minnick 33:37
Yeah. And then for the folks listening, listen to the audio podcast. If you're not make sure you subscribe, you can get the dotnet on AWS podcast anywhere where you're streaming your podcast from. But basically, what we've done here is we've added an attribute to the parameter. So we're inside of the is null or empty method or looking at the code inside of the is null or empty method for string. And we know that the is null or empty method has a parameter string value where we pass in our string to see is it null or empty? And this is where the attribute is the attributes on the parameter. So yeah, I agree with you. It definitely reads a little strange plus the attribute name being not know when. And then you have to specify a return type from the method. So since the method returns bool, we know that this parameter that the user passes into us is not know when that bool the return bool is false. Like it does make sense but it also doesn't make any sense.
Maarten Balliauw 34:46
Exactly, exactly. But it is there. It is super useful. I've a couple of examples where I'm using this exact attributes that you can use in your own logic as well. Now, before we go there, there's one thing I want to hightlights very Often, if you don't know about those attributes, what will happen in the example of our swagger five methods is that when, when you pass in a value, and you get back this nullable string that you have there, a lot of people will suppress that warning and just add an exclamation mark saying, Look, I know better than, then the compiler can return open. And now the code is essentially the same as what we had before. Now the problem becomes if the parameter that you're passing into the slug of five methods comes from a database, for example, and you have no idea what's going to be in there, you're lying to the compiler at this point, you're saying, Look, compiler, I know better, I don't even know which values might get passed into this like a five minute but I still know that this is never going to be no, which kind of defeats the purpose of this nobility feature in C Sharp, so I would say, learn about those attributes, stop suppressing with the exclamation mark, and just annotate whenever you're in control of the code so that you don't have to use that exclamation mark. I have Brandon. Before the show you were asking and you were saying that this exclamation mark is really an anti pattern and people are using it. I
Brandon Minnick 36:10
hate every pull request I see with this exclamation mark in it. Specifically, the no forgiving operator, exclamation point, exclamation mark.
Maarten Balliauw 36:21
Yeah. So there is a quick fix in writer where you can say, okay, remove redundant suppression, when you have one where you don't need that check. But also, there's fine nullable warnings suppressions as an action that you can use to find all occurrences where someone is using the exclamation mark to suppress something. So this is really good. If you need a list of places where you can shame people and then look at the kids get history. And the person who wrote this, this is perfect.
Brandon Minnick 36:49
Yeah, cuz the the big problem I have, and we should zoom out for anybody who hasn't ever used this keyword before, it's, it's literally the exclamation point or the bang operator. And like Martin was saying, you can just append it to whatever you're working on them might return null. And then you can just add an exclamation point and say, Hey, dotnet compiler, this will never be No. But the problem I have with that is code changes all the time. And especially pretty much all of my, my code is in open source projects, anybody can contribute. And so that code will eventually change. And we're gonna run into a point where a no value does come back that we don't expect, but because we're suppressing it with the exclamation point with the null forgiving operator, it doesn't essentially trickle down and show up in the rest of our code. So because a lot of this code is cascading forward, like you have a method calling a method, there's probably another method that calls this method. And it's if we don't pass on the correct information all the way up. Well, now we have code written elsewhere, that assumes we'll never get a null value back. And we're just making all these assumptions. And yet, when we put this No, is it no forgiving? I say that right. It's,
Maarten Balliauw 38:15
I think it's a no forgiving operator. It's also known as damage damage operator, which
Brandon Minnick 38:20
had been greater. Yeah. But essentially, what you're doing is you're you're hurting future you by saying, Yes, I know better. And this code will never be known. Because the codes gonna change at some point. So to me, yeah, the exclamation point is just, it's a future null reference exception waiting to happen. That's, that's why I've never wanted in my code, like, let's handle it. Like, if we if we do think that this should never be No, a lot of times what I'll do is kind of similar to what you did earlier, Martin, where you did question mark, question mark, and then you put in either a value that returns back when it's null, or if we've truly think it should never be No, a lot of times, I'll do question mark, question mark. Then I'll say throw new invalid operation exception. So I'll say like, this should never be No, like something bad happened here. But by throwing that exception, it also points directly to the line of code where it happened. And we add in this message that says like, if this context is no, like, we never planned for this, we never thought about it. Whereas when you get a null reference exception, actually thrown by the runtime in your code. It's the most unhelpful exception, it doesn't even tell you what was No. So you then get to spend the rest of your day trying to figure out just where this exception came from, and why whereas at least, if I'm the one throwing the exception, I can say, hey, I never thought this could ever be No, I never planned for this. Here's why. And then, you know, future me can go back and be like, Oh, okay, I remember Yeah, a couple months ago, looking at this code. Okay, got it. Now, I can like pick up where I left off, whereas, yeah, that no reference exception. is just the most useless exception. So hard to go fix there.
Maarten Balliauw 40:08
Speaking of nullable null reference exceptions, there's one more thing that I do want to stress here. Imagine with our slug of five methods that we change it up a little bit and say that it will never return a nullable string. And the argument is also never going to be no. What you will see after changing those and just saying, Look, this is not annotated, so it means it cannot no longer return null. What you'll see is that the IDE, and your compiler will say, look, you're having a redundant null check there, the code didn't change, but you're still checking this value for null, do you actually want to do that? What's interesting is that you can ALT ENTER and do something like okay, remove this check or whatever, I will see if this code would be used by someone who is using older versions of dotnet, or F sharp, keep that null check there suppress the fact that you should not have this null check. Reason for that is nullability is a C sharp only feature. So if you are distributing your codes, and you have no idea which runtime will execute the code that might not support nullability, when people are editing things or running things, you still want to have that nailed check in there. Even though, based on annotations, you're saying that null is never possible in this case?
Brandon Minnick 41:23
Yeah, it's a really good point. And I would take it even a step further and say that somebody might be using your code, and they might not have nullability enabled. And so they can totally pass it in and no string here. And base will have, they're gonna face repercussions certainly, like the code is gonna break. But the IDE is not gonna yell at him for doing that. In and so, in a lot of actually, I think every public API like, we were chatting before the show that I'm still lead the dotnet Maori community toolkit. And yeah, and a lot of our public API's, I'll still do argument, null exception dot throw, if at all. And even though we have no ability enabled, and it shouldn't, nobody should ever use this. But yeah, if somebody has no ability turned off, then they'll do it. They'll absolutely do it. Yeah.
Maarten Balliauw 42:22
I'm a little bit sad. Not sure if you guys ever saw that Microsoft was thinking about adding another operator, which was two exclamation marks, when you had six years, I bought it, it still kind of sets, I'm still kind of sad that the community decided that this was not a good idea. What it would allow you to do is in this slug of find methods where you pass in a string value, you could add a double exclamation mark at the ends. And then you would get a check for argument, null exception. And by the way, this was writer in action. So if you just type exclamation mark, exclamation mark, you will see that you get a null check for free. But the compiler would do this if C sharp would would add it's so I cannot really show it because I'm trying to type syntax.
Brandon Minnick 43:12
Yeah, I it's one of those like, I agree with the points against this, like we're adding in a new keyword. And there's scoping problems with it. There's also the fact that this is a keyword that can be used anywhere in your code. So what if we do bang bang in other places, what happens and there definitely needs to be more thought put into it. But But yeah, the idea of having like, basically the method definition, be the guardian of all of this for me, oh, my god, like I could rip out so much boilerplate code and replace it with just one dotnet keyword. I was so excited. And I was sort of the guy on Twitter that was responded to people. I was like, if you don't like it, don't use it, but I want it. But yeah, I think it was the right move to just hopefully just delay. Hopefully it's not God forever. But yeah, give some more consideration to. Yep. Is this really the best way to do it? But man, yeah, having having the method definition, just do all this for me. Because now that we live in this post nullability world, like we were talking about a minute ago, there's still some people who haven't entered into it, or people are gonna opt out of it for reasons and it sucks that we still have to have that cognitive load on us as library creators and like, well, nope, somebody can still do it. You know, it's not illegal. So we have to check for null even though they shouldn't be passing it. No, because I told him not to pass it. No, that hopefully someday it'll come back.
Maarten Balliauw 44:46
It'll come I'm not sure of it. But I'm almost sure it's, we need it. We need it. David Fowler, if you're listening, we need it.
Alright, what else is there? So yep, I mentioned those attributes, there's a couple more attributes that you can use. I have a couple of examples here that I might want to show on screen just to show you what is possible. So we already saw this not know when we're not null attribute that you could place on a method saying, Okay, if this, if the value I pass in as an argument is not null, then return value is not going to be no. And there's also a couple of places where you can use attributes to, to change the direction of when null is possible. So imagine you have a person class that takes a username. And the default username that you will have if no value is set is just going to be a random good. So people can optionally select their username. But if they don't, it's just going to be good. So what you can do in such a class is, first of all, initialize the username in your constructor so that you have the going by defaults. You can have a property that is getting the username, and you can annotate that property with just saying string and annotate. It's saying, look, the username is never going to be null when you read from this user name property. However, you can also add the allowed null attributes on the entire property saying, Look, I will allow people to pass in null into this specific property. And what's going to happen there is that when this one is null, I'm going to manually set it again to a go it's to a new codes as your name. So this means that username is kind of optional, in that there's always going to be a value, but setting the value is optional. And if I set the value, I'm even allowing nulls so that I returned to the default behavior that I have there.
Brandon Minnick 46:46
This, I've, I've seen this attribute before, I've seen allow no and I've never understood why it exists until right now. Are you? Does Yeah, this, this totally makes sense that we have a property, so it's gotta get her it's got to set her. We don't want it to be no. But if somebody passes in a null value, we're going to add in the logic to handle that for them. So it's almost like we allow you to pass in null to this property, but it'll never be know when you're reading from it. And that's why the property allows No, I get it now. Why wouldn't you just add, like the question mark to it, or, like using it on methods always confused me. I never understood using our methods. But my goodness, yeah. Properties that makes a lot of sense.
Maarten Balliauw 47:46
Yeah, there is, by the way, also the there is also the opposite. And that's the maybe no attributes where you say, Look, this property together might return null. But the setter always requires you to set an actual value and never can be null. So let's say you have a person with a middle name, property, not everyone has a middle name. So what you're saying there is if you read middle name, it can be null. So please do a null check. But if you set the middle name, then I know that it's never going to be no. Fascinating. That's the opposite way. Again, same thing.
Brandon Minnick 48:22
I've seen this before. And I'm like, Yeah, I mean, if it may be No, I'll just make it nullable. Like, why? What a silly thing to exist. Why does this thing? Yeah,
Maarten Balliauw 48:33
and you get this discrepancy between reading and writing. And depending on how you're consuming this middle name property, you might be tempted into adding those exclamation marks to suppress the novel warning, which defeats the purpose of the entire nullability feature. You want that information there.
Brandon Minnick 48:49
Yeah. I feel like I've got a bunch of code refactor. Now.
Maarten Balliauw 48:57
I have one more, which is also kind of backwards, but also very interesting. There's also the member not know when attributes so I'll first walk you through the code that I have here. So I have a person class, which has a nullable location string property, which means that the location of the person can be no it cannot be null but also it can be null in this case. However, there is another property which is called has location. And to that has location methods, I'm doing another check for location whether it's true or false. But to this specific property, I can add an attribute that says member not null when the return value of as location is true, then location is not going to be null. So this essentially means that if I do a person that has location later on in my codes, C sharp we'll treat that as a null check because it knows if has location returns true location is never going to be null in this case. So you will see that in the IDE if you're watching this the stream You will see that if I do my hands location check, there's no squiggle underneath personal location. Whereas if I'm in the ELS branch, you will see there is a squiggle and possibly V referencing and allow reference.
Brandon Minnick 50:15
Yeah, I like this one I, I've gotten through an ad of this. And yeah, my, my open source projects, because I gotta imagine it's going to help out future me sometime. Yeah, it's one of those where it's like this, this method runs and when the method finishes, we know that these certain values are never going to be no. So yeah, let me just slap on the member, not null attribute. And someday in the future, I'll be able to call this method and not have to do another null check.
Maarten Balliauw 50:48
It's fantastic. Yep.
Brandon Minnick 50:52
Yeah, and kind of a similar pattern to like when we have a method that has an out variable. So you see a lot of like, try parts where that OUT parameter might be No, if it failed. So if TryParse returns false, then we know it didn't work. And obviously, we have no results. So it's still false. But if it did that, obviously, that variable is not known, because we did parse and that it succeeded. So yeah, I love that you can just say like, if try parse, you get your OUT parameter, and then you can just start using it. You don't have to do a second. Is this also know? Which Yeah, seems so redundant.
Maarten Balliauw 51:33
Cool. I can do one more since since we still have some time. So I'll not show you the null. The the attributes that exist, there's a bunch more, maybe I should also share those for the show notes. There's an MSDN, or Microsoft docs page that has all of the attributes with some examples. So definitely go through them. They're super useful. Let's maybe shift gears a little bit and go into Okay, I have this existing code base, I know that for existing or afford new code nullability is enabled by defaults. How do I go about converting my existing code bases using null because I'm convinced that this can actually help me trap null reference exceptions. One way to go about this, there's a couple of things and also share the my blog post on this for the show notes. But one of the hints that I typically have is use a tool that allows you to create a class diagram. So Visual Studio Professional does this writer does this. I think independence is another tool that you might be using, what you can do there is typically open up a diagram that shows you all of the types that are in your solution. And typically where you want to start.
Brandon Minnick 52:44
Click on there.
Maarten Balliauw 52:47
Yeah, apparently, my context menus are not showing. So you can essentially select a bunch of classes, and then show diagram and show your class diagram of everything that is there.
Brandon Minnick 52:55
So highlight a bunch of classes, right click Show diagram. Exactly. Yeah. Wow, this is cool. I didn't know this existed. Awesome.
Maarten Balliauw 53:05
The cool thing about about these class diagrams is it gives you an idea of who is depending on different classes who is making use of these classes. And typically, you want to start on the edges of your application. So typically, data transfer objects, or plain old C sharp CLR objects. pocos, if you want to call them that are good candidates. So if you look at this class, for example, my location for there has only incoming dependencies, but no outgoing dependencies. So that means if I make some changes in here, there's going to be at least three because you see three arrows, three locations, where I get the benefits of adding this information, this mobility information, and not having outgoing references here means that I don't have to worry about dependencies of this class. I mean, this nice, self contained area of my application. So this is a good candidate to start with. Another one would be this country class that you see on screen here, for example, only has incoming references, which means no dependencies that it has by itself. So it's a safe one to start with adding availability, and immediately get a lot of benefits, at least in six places in codes depending on the ROC see here. So this is a good place to start. Very
Brandon Minnick 54:20
smart. Can you do that with the whole project?
Maarten Balliauw 54:24
You can, but depending on how big your project is, you will get a squeezing diagram that doesn't really tell you a lot. However, you can do filtering like group by namespaces, and so on. So you can still see how two namespaces interact with each other. So it helps to slice and dice, but I would say maybe focus a little bit.
Brandon Minnick 54:43
Yeah. And just to fill in some folks in the chat. Edward TV is asking what the demo is about. We're so glad you're here. You're here to join us today. We're talking about nullability today, but right now, Martin showing off a really cool feature in JetBrains that I didn't even know existed that you can show all the relationships between multiple C sharp classes or, or JetBrains will do that automatically for you. So showing this off as a way to see which classes have the most references are being used the most in your other code to then know go in and start there with your knowable attribute types. That way you get the most bang for your buck. But yeah, this is this is really cool, Martin holy cow.
Maarten Balliauw 55:30
Maybe another tip is when you start, there's the option to either annotate or refactor a little bit. So let's Yeah, we still have a couple of minutes. So let's maybe quickly go into that. So if we would start with this location info class, you can see that my country and location here are not annotated. So I can enable nullable reference types for this file. And what will happen is that I will have to find where I'm actually passing in the country and location into this class so that I can check whether there's a potentially null value, whether I should annotate my country and location, after all. So what you can do is on each property, the ID will typically give you the option to inspect, so right click inspect, and then show value origin. And what this one will do is give you this reverse call stack of where you're passing in values into that property. So really useful to Visual Studio has this writer has this and so on. I can go in there and see, are we potentially passing null or not. And here you see, I have two occurrences where I'm actually passing in a string, Belgium and unknown, this is good. But apparently, there's also this new location info where I'm passing in something that comes from a database and is potentially No, at this point, I have the option to either go annotate my location for and say, okay, country can be no, but maybe a better way here is to check my country dot name for null. And if it is indeed null, just return a new location info that has some default values. So depending on what you want to communicate with the consumers of this library or of this class, you might either want to return something that is never know, or something that is that is null after after a while, I would say it really depends on the situation, you can make this property nullable if you want, but that doesn't mean that all of a sudden you leave null checks all over the place. Or you can return a default value and then you don't no longer need those null checks that you might expect. So these are two options, either add an annotation or rewrite the little bits.
Brandon Minnick 57:33
So cool. Well, Martin, like you mentioned, we are we are running out of time we get kicked off at the top of the hour, whether we finish or we're still talking mid sentence. So if you want to say Martin, thank you so much for joining us. I know I learned a lot today that I never knew about JetBrains and nullability. Certainly so really appreciate the knowledge. Hopefully we can have you back on again in the future to keep teaching us more. And think thank you for watching. Thanks so much for joining us on the show today. If you're listening to the podcast, thanks. Make sure to give us a rating leave us a review help people find it. And if you're not, make sure to subscribe. We have the dotnet on AWS show audio podcast. We're here every two weeks, the Twitch channel every other Monday at 8am. Pacific. You can come join us as we talk about AWS on.net. With that, we'll see you in two weeks
Continue to The .NET on AWS Show, featuring Diana Pham
Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.