What's new in C#? Exciting new features in C# 8.0, 9.0 and 10! - Filip Ekberg - NDC London 2023

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right I think it's ready to get started welcome to this talk we're going to be discovering some really exciting features that have been added to c-sharp over the past few years c-sharp is one of those programming languages that keeps evolving and it's taking inspiration from other languages such as if sharp kotlin Swift Java CC plus plus and a lot of other good programming languages as well so it's exciting to look at what's been added to the language because quite frankly the past 20 years has been quite some ride for a c sharpen.net developer so we're going to be talking about everything from C sharp 8 to 10. there's a talk on Friday that goes into details on all the c-sharp 11 features that were just released but if you haven't been working in c-sharp for these past few versions there's quite a lot that we need to discuss first my name is Philip Ekberg I'm happy to take questions afterwards if you don't agree with any of the language features it's not my fault so don't throw anything in my face but I'm happily here to discuss all language features.net c-sharp and whatnot and you can always pay me on Twitter or send me an email as well so this here is a tag Cloud that I usually show around what's been added in c-sharp these are a lot of the important language features some of them change how we architecturally have to think different when building our applications when using async in a weight for example doing that prior to adding the task parallel library or even adding these keywords in the language was not a trivial task most of these things added to c-sharp except some things like generics have always been able to you've always been able to do that with c-sharp but with a little bit more code so the idea with adding new language features is to avoid more keystrokes make it easier for us to express ourselves in ways that were previously a little bit more difficult so a lot of what we're going to discover here today is just compiler magic the compiler is going to do a lot of heavy work for us some of the features we're going to discuss are as important as generics and async and the weight and I have quite a few examples of how we can use this and how they will change the way that we look at our applications now if you're like me and you love programming languages there's a GitHub page they open source the compilers some years ago and you can participate in discussions around what's going to come in c-sharp some features that have been withdrawn from the language and what's interesting in that is that Microsoft has recently invested a lot of time in some language features that got a lot of backlash from the community so they listened and they removed that and the rest of the community didn't like that so no matter what they do people are going to get upset but GitHub is here so we can discuss around these language features so you can always go in here if there's something that you want to learn about because the comments here contain a lot of details on how you can incorporate this a lot of the documentations for Microsoft usually have the normal this is a dog and this is a cat but I have no idea to use how to use this in my Enterprise application but the comments are filled with great additions to that so with that out of the way I just want to start off with some highlights from c-sharp 7. now C sharp 7 was one of the first versions of c-sharp where they did a point release so they released c-sharp 7.1 7.2 7.3 and that's the only time they've done that so far I believe this was a proof of concept that they could release the compiler separately from the whole.net ecosystem and from Visual Studio effectively it's just a nuget package you could update that and get the latest compiler and you get access to the latest features of c-sharp one of those features or quite a lot of the features added to c-sharp 7 set the base for what's going to come in C sharp 8 9 and 10. but it's a long Horizon so they add a little bit of a language feature a small portion that will eventually end up being something quite big and pattern matching is one of those things they first introduced in C sharp seven but as you'll notice later pattern matching in c-sharp 7 wasn't really ready for anyone to use because it required a lot more keystrokes than what the equivalent would have been in the past but it still set the base for what's going to come next before we get to that let's just talk about one feature that changed c-sharp now other programming languages have had tuples forever but c-sharp did not until c-sharp 7. this here is how you'd use topples in.net and c-sharp prior to c-sharp 7. there's a type called Tuple and you that's a generic type and you use it like any other generic type but then it's really difficult when you want to access the items on this thing you have no idea what they are so with some compiler magic and some really smart people at Microsoft they added this as a first class citizen in the language it's a little bit different syntax but this here creates the same thing behind the scenes this uses that same generic type and with some magic compiler annotations we can get some information about the variable names and the field names here using this on its own allows you to return multiple return types from a method or accept types that has multiple fields on them if you don't want to create a class for Library struct which is quite handy but where it becomes even more powerful again is with pattern matching you'll hear me say that quite a lot at a lot of these features set the base for pattern matching something that came along with this which is quite confusing is this magic method if you add this to a class it will allow you to do certain things with that class or an instance of that class the method is called deconstruct it's not to be confused with a finalizer or a deconstructor but it is a way for you to take an instance and pull different parts out of that instance for example in this case here I did say that using persons and cats and dogs is a really great example I should really follow my own advice but then again this here allows me to grab the first name and the age out of this person it's a normal out parameter which you might have used in very early versions of c-sharp but where this is different from what you've done in the past is that I can now take an instance and I can do I can I can assign this thing here this instance to um to what what looks like a tuple here on the left hand side this is also just compiler magic it insta it creates two local variables it sets that into the out parameter allows you to set the values into those fields so while it looks like a tuple it's not really the same thing but they're very often confused together or used interchangeably but this is nice we can use this again with pattern matching and I'll have a good example of that as well later on but first we need to understand everything else so tuples or tuples depending on where you're from or how you'd like to pronounce that you say other tuples or tuples but we really talk about the same thing a tuple can be a sign like this here this is a tuple assignment assigned to a local variable called coordinates I can access those fields very nicely very convenient I could even return that as a named Tuple from a method which is also very convenient again multiple return types is sometimes a good idea but when you end up having 20 multiple return types it's not it's it should use a class that's where we can use that class right so I can take this instance and I can assign that into two local variables which looks like what we have on the top here but the bottom one creates two local variables the top one is a tuple and this here is all done or the last portion is done by introducing this magic method so the compiler will know that you have this available and therefore the syntax also works so far we haven't really looked at anything that requires a change to the runtime right this here would be easily translated into C sharp one two three four or five right that's the fact with most of the language features that you can use in c-sharp it's not supported but you can use newer language features no matter which.net version you're using or dotnet framework version you're using some features as you'll notice require runtime changes as well and visual studio or whatever compiler or environment you use will tell you that you need that in case you hit a wall but since most of this is compiler magic and compiles down to the same IL that we've had in the past many features work with older versionsoft.net as well with that being said we've just covered some of the basic features in C sharp seven that we need to understand to go forward now C sharp eight I just showed two features of C sharp seven so at this point does it feel like C sharp eight and Beyond can add much more to the language obviously if if it wasn't much more to add to the language I wouldn't be here so of course there's quite a lot to add to the language but you'd imagine that the eighth iteration of the language couldn't add a lot of features but take a look at this feature set here we got something called read-only members default interface methods or default interface implementations depending on when you're reading their documentation pattern matching enhancements really pattern matching enhancements is not really appropriate to call this because it's totally revamping how we use pattern matching we're getting using declarations static local functions nullabable reference types asynchronous streams a synchronous disposables ranges and indices null equalizing assignment and there's a few more features as well now if you look at other programming languages I don't think I've seen many that introduce groundbreaking features so often as c-sharp do but c-sharp do it because they look at other new programming languages that have these very important and smart features they take inspiration from kotlin Swift and Java and other programming languages as well the same thing here so C sharp can still be improved and a few of these I've highlighted or bolded the pattern matching enhancements and all the reference types and asynchronous streams we're going to be taking a deeper look at that and understand this but again at the eighth iteration of C sharp they still quite a lot to learn if we want to use this now it I said earlier that you can use the new language versions with with whichever framework or net version that you want that's partially true some of them do depend on runtime changes so you have to be on vs 2019 or later to use C sharp eight and Doctrine core 3.0 or later you should really be on.net6 if you're doing any new applications today or if you're looking at upgrading it's easy for me to say that you should go with.net6 but upgrading to that might take a little bit of time and especially some of you use anyone here doing WPF or win forms on.net framework there's quite a few so you're probably wondering or thinking like well hey all of this is useless because I can't do.net core well you can actually do that now you can use.net or the new.net thing it's really confusing what you should call this new thing because it's a framework but it's not.net framework it's an incorporation of.netstandard.net core and Dot and frameworking one thing and it's just called.net but we can use this to create WPF winforms and uh and other types of applications as well now you'd probably imagine that it's just as a little flag that you change it it's not that would have been too easy so you have to actually create a new project that's targeting the new.net version move all your winforms or WPF stuff over but that will then give you all the performance improvements made in.net it will give you access to all the language features that do require runtime changes but if you don't want to do that you can always try and toggle a new language version as well you can override the version of the language in the Cs prod file to tell it to you c-sharp 10 or 11 even if you're running on.net framework 2. you can try that and see what happens what happens is that Visual Studio will tell you that hey you should probably not do this this is a shared Library that's shared between two different types of projects I compiled this for an older version and it's now telling me that the Target that you're trying to build this for doesn't support this language feature if I simply remove the usage of the language feature in this file the error goes away so the compiler is smart enough to be able to compile that using the latest compiler as well this error here brings us into an interesting language feature called the default interface methods or default interface implementations this is one of those features that really divide people into two different groups either you really hate it or you just don't like it that very much I'm kidding there's probably a use case for this I shouldn't be too hard on them so this here is an interface now we've all used interfaces probably and now this is an old one that doesn't have it returns an object and I'd really like to improve this to return a generic type instead but if I do that and let's say that this is a shared package or a shared interface in my entire company if I deploy that to nuget people are going to get really upset if they have to you know upgrade their applications to implement my new method there's ways around this people have subclass people have introduced abstract classes instead to try to work around this problem but what Microsoft decided was a great idea is that why not allow method implementations in interfaces that provides a default way of how this method is going to work so now I'm not going to break anyone what happens now is that no one has to implement this method here at the bottom if I upgrade my nuget package or if I add this to an interface in my application Visual Studio won't tell me that I have to implement this it won't even tell me that I haven't implemented it and that it's available so I have to go into the actual repository or have to know exactly what's in this interface to know that this needs to be implemented which is a little bit annoying but it's great for Library developers and that's one of the use cases that I see this being useful for if you have a library that's used by a lot of people and you want to break changes but you don't want to upset people you could always say hey throw new exception or whatever and if they happen to use this someone will find out eventually all right so has anyone used this feature no one that's what I expected all right and you probably won't but you will see that if someone else do this and you bring in a new good package or something from GitHub don't get confused why Visual Studio isn't telling you that you're not implementing one of the methods that are available because there might be a default implementation available this is one of those features that require the runtime to understand the language change because previously the interface was a contract between the consumer and the class right so how would you run a method on something that's not available on what implemented the interface all right so the actual useful feature of c-sharp 8 that I very much like is something called nullable reference types which again is a confusing name but naming things is really hard we've always had reference types that are nullable in C sharp so why give it this particular name what this feature is doing is that it's changing the way that reference types are looked at by the compiler the compiler will now think that every reference type has to be set to an instance you're not allowed to have nulls anywhere so much like nullable value types where you explicitly have to say hey I want an integer that's nullable by adding the question mark you now have to add a question mark to indicate that you want a nullable reference type which is very handy because we've all probably had this happen right has anyone never seen this screen before you are lying I don't believe you or you're new sorry but we all eventually end up having this so why not get the compiler to help us with this because there is one big problem where there's multiple problems with null ability first it encourages that we add null checks all over our code base even if it's not really necessary that makes the code harder to read doesn't necessarily make it hard to understand but more noise means that there's it's easier for us to misunderstand something it's also ambiguous but does it actually mean when a method returns null let's say that I'm trying to fetch a record from a repository personally I always try catch everything and return all but if there was a problem connecting to my database should I get null which is the same result that I might have gotten if there's no record in the database I should probably handle those scenarios differently so we don't know if it is actually unavailable or if it's not found or if it's an error instead we could work with subtypes user not found the user unavailable or through an exception with the database operation fails a bigger problem is that it encourages mutability that means that we can change objects if something is set to null someone expects this to be not null at one point or another because otherwise why would we even have the property or class to begin with so why is that a problem well nowadays everyone's using tasks and task parallel library and doing mobile applications and doing async in a weight and all of that threading is a lot easier but handling multi-threaded applications has not become easier so it can become an issue when it comes to multi-threaded Applications because you will eventually end up having race conditions and trying to update things from different places where you shouldn't so how can we get some help with this we can ask the compiler to solve something for us because I really don't want to end up having to write this all over the place someone in here is going to tell you hey that that code doesn't look very nice we can simplify that a little bit but I still would prefer the compiler to tell me that this could potentially be a problem if the compiler could determine that person address or Street will never be null this null check would be unnecessary and in some cases it can do that we can help the compiler as well to indicate how how we've handled certain fields and objects and how do we do this we enable this by either using a compiler directive we can say that nullable is now enabled for this method for this class for this namespace for this file we have a setting in our application or the Cs project file that allows us to enable this for the entire project and since.net6 this is enabled by default what's the first thing that I enable in Old projects as well but we'll get to that soon so what happens is that when we enable this we can obviously see that string name is equal to null here we say problem because I'm explicitly saying that it's null but the compiler is now it's not telling me that hey there's an issue here or it's just giving me a little bit of a warning imagine if this was all of a sudden giving me compiler errors that would be a little bit annoying and the feature that no one would turn on so instead it's just giving me a warning for now most of us look at our warnings tab all the time and fix author warnings in our projects right you're lying again all right so to to make it actually work with knowledge we'd have to say string question mark and then all of these errors would go away but we can see here that it's telling me that name maybe null here and it's in fact very much correct because I'm setting it in all on the line before it's much smarter than this I have an example we'll jump into Visual Studio in just a moment but what I do I'm a contractor so I go to clients and I enable this and I also set trade warnings as error to true I check in my code and go home and then all of a sudden stuff breaks and they call me back no I'm kidding let's have a look at how this actually works but this is a great setting and it is something that I encourage you to enable in a new project because it will then encourage you to fix the problems because no one reads the warnings so I'm in Visual Studio it doesn't matter which version we can enable this for anything that's c-sharp 8 and newer there's no warnings everything's green here there's no issues found I have opinions on my own code but that's another another talk so now what I can do is that I can enable this by either using this compiler directive to say that this is enabled and all of a sudden I get two warnings here at the bottom it's warning me about this particular class that this class has two properties that are public there are they are never set so what I can do is to fix this I should obviously set them to a value and it would be appropriate for a Constructor to set this value if I just introduce an empty Constructor the warning goes to the Constructor and set instead because the compiler now deems that this should be set by The Constructor you have two fields or properties that are not set so first string last let's initialize this uh nope first right and hopefully after this if I can manage to type on this keyboard last name oh come on here we go and the warning is now disappeared so that's great but now I've broken the contract with everyone that's using this class which is not very good so I don't want to actually add this I want to get rid of the Constructor because I want to know honestly the problem with null reference exceptions was never in this class the problem is where someone uses this first name incorrectly or uses this instance incorrectly so to move the arrow to that place we can add a question mark to say like hey the string here can be null and this string here can also be null and before I go anywhere else I want to tell you about this keyword as well this keyword is instead of set you can set it to init which means that you can only set this once you can only set it once you initialize the instance using an object initializer after you've initialized the object it's immutable and with c-sharp 11 you can also say that this is required to be set if I can spell required there we go you can say that you have to set this otherwise there's going to be a compiler error there's a lot more characters here than adding a Constructor but then again this is a way to work around that we might have nullable types that are set by object initializers it's a transition Phase 10 years from now probably or hopefully no one will have to use the question marks all over the place now I fixed this class but there's no warnings anymore in my my application I now have to go go ahead and move this compiler directive to all other methods in my class I don't want to do that so instead let's get rid of that and this can be done from the property page it can be done from the Cs proj file it's easier to find in the Cs project file because I've already added it so I'm setting nullable enabled and I'm also going to treat all warnings as errors inside this project I'm going to save that and go back to my program and hopefully now we have a few errors instead now it's telling me that we have this details which is an instance or a property that represents the details of a person this is not a problem either I don't add a Constructor this is going to be allowed to be null right but I still have a few errors and let's go ahead and fix them this we can just look at the code here I'm getting an attendance I'm calling this who is here method and if we look inside this method call here we have a place where this would blow up one way to fix this is to use a very handy feature called argument null exception and I want to throw an exception if if this thing here if details is null here we go notice how the warning disappeared when I performed a null check in the line above there's something called null State static analysis if I say that 10 times first what's what that's doing is that it's trying to analyze exactly how your code is using an object or using that reference it's trying to determine if it's been null check or not and the fact is that this method here has an attribute on its in parameter that says if this method does not throw an exception I promise that I've performed a null check it doesn't have to perform the null check so if the method is lying you still have a problem we can check this in multiple different ways I could also say well if if the person dot details is not null go ahead and do that so it's very smart it can it can even figure out the inverse of that as well right we can invert that and it would understand that as well super smart and if I want to allow the person in the list to be null I could say that this method here accepts a um a nullable a list of people that could be null and then I would get another warning again so we can keep on adding this to places in the application and we'll eventually find where null reference exceptions would be appearing there's multiple different ways to handle this and solve this and work around this as with anything there's one more warning in the class here and that's this method here is telling me that I'm doing something that I shouldn't here I'm saying that well this method is telling me that it returns an instance I could say that I allow this to return null but then again I would have a problem somewhere else instead I want to fix this I want to promise that I performed either a null check and what's returned here is not null Microsoft introduced the damage operator to say that I promise that this is not null this here is going to blow up you're not smarter than the compiler so very rarely do you have to use this so instead we can solve this by saying I want to return a new person and I want to set this with a new details where the first name is or the first name actually I forgot yield I have to do yield return and I can set the first name to something why is it complaining oh well let's get rid of the required C sharp I said that I shouldn't show any C sharp 11 stuff and I do that and I break my own demo here we go this here might be confusing what is this thing well we've all seen when we can do for instance me person right but why having to add these extra characters that's a little bit unnecessary the compiler can use this thing called the target type new expression which is a new feature in c-sharp as well so what you can do is that you can figure out that you want to return a person so why not just create an instance of that it's not always going to work most of the time it will so with that being said we've now fixed the problems of finding all the null reference exceptions in this application and I do encourage people to go ahead and enable this in your applications and try and figure out where you get these exceptions the first thing you'll notice is that you'll get them on your dtos and your domain objects but once you start adding the question marks and allowing things to be null you might see it that pops up everywhere else all right now with that being said I also do encourage people to turn on treat warnings as errors not just to uh be annoying but because it actually helps people will fix problems if it turns up and if the build server blows up people will eventually go ahead and fix that so with c-sharp 8 we also got what's known as asynchronous streams this is another way of looking at data that's coming into an application so let's say that I want to consume messages on a service bus previously you had to do all your own custom connections to that use some third-party libraries it wasn't really all that trivial with asynchronous streams you could use for each Loop to very easily say give me all the messages on this as they come in use a normal for each Loop you handle it I can normally do and it's very easy to consume streams of data compared to to previously let's um let's jump into Visual Studio actually let's let's do Vega's code instead to spice it up I'm going to go into vs code and this method here is going to produce a stream of data you see the async keyword that I have here normally you use that together with a task to return something that's running asynchronously but in this case here I'm using it with something that's task like I'm saying that this method here will produce an i innumerable where each element that I retrieve asynchronously will contain a string if you've never seen async no8 this is very confusing and I understand that but hopefully it's easier to understand that what you had to do in the past so then the first thing that I do here is that I open up a stream to a file that I have on my disk I'm using another new language feature called using declaration look at I have this using VAR stream and then I just have the semicolon at the end it's not wrapped in a using statement that like you normally see because what happens with a using declaration is that it promises that it will clean up after itself when the method completes and that's quite complex in a synchronous context like this here so then what we do is that we have a while loop that's going to read through all the files that I have on my in my file read through each line it's going to say I want to get the next line available in this file if this is a line or if this is actually a string that I got returned this is pattern matching we're going to go into that soon I'm going to capture that as a local variable called string and then I can use this inside this this while loop now this is interesting because I previously had to declare this on the line above use out parameters and it wasn't very beautiful this is much more nice I have the await task that delay to simulate a little bit of work let's say that we're grabbing something off a message box we're doing some processing of the data that we're loading and then I'm using the yield keyword again to return this to the iterator or I'm telling whoever is iterating through this this stream of data that there's something available looks complex but this is the producing side of that stream which is also important to understand but often if you use for instance Azure and I used Azure messaging as an example their apis will already do all of this part inside of them so what you need to focus on is how we how we how we consume this and that's very simple as well so I have this await keyword in front of my for each Loop normally you see see something like this here for each line that I get of my chunk of data I want to process each of that that this here would indicate that you're getting an innumerable as a result out of some asynchronous operation if we put the away keyword in front of the for each Loop it means that I have an i enumerable that will produce elements asynchronously from this method called here and then we can use them inside this method or inside this for each body what's interesting is that it goes ahead and calls that method gets the first line you then get returned into this portion here you can process that if you want to continue it then goes ahead and loads the next one normally when you load a chunk of data it loads all of it but this here loads one at a time right let me just show you exactly how this works this error is going to print my favorite song If you don't know the song or if you do you can sing you don't have to all right so that's pretty cool now with a console application that's very simple with a text file that's very simple but it becomes quite powerful when you use this with things like a message bus or queues or anything like that so the synchronous streams are composed of two different parts it's first it's the way that we produce the stream of data this here indicates that we are going to stream something it's a string that will be streamed back to us we're reading one line at a time and then I'm using yields to return that which is a very handy keyword that's very rarely used it should really be used more often instead of having to create your own temporary lists and so forth in this case there's no other option you have to use yield and then we are then telling the iterator that we want this and we are opening the file this is a little bit of a different um way of saying or stating the same thing that I had earlier each item here is retrieved asynchronously I'm setting that to my local variable and I'm doing some processing and then I return that so this is the producing side of that asynchronously numerable and then consuming this is very simple I really like this and this is this together with nullable reference types and together with the pattern matching enhancements that we're going to look at soon in C sharp eight we're really awesome but before we look at pattern matching they've done some more changes in c-sharp nine that I also want to bring into that sample as well or that that that demonstration C sharp 9 again introduced a whole lot of features that help us build more cleaner software use less keystrokes because someone else did it for us we can do something called records and we can use this very very good type that was I believe one of the primer reasons that they started doing the rework on the compilers in the first place when the compiler is Ford for the open source compilers when they started doing that one of the Champions was primary Constructors which is really what record types eventually ended up being so it took them four or so versions to get this into the language which shows that this time this thing or this language feature is no easy task to solve that was released together with the init-only Setters that I demonstrated earlier and the top level statements that you might not have noticed but the application that I had in both vs code as well as in Visual Studio none of them had this public static void main stuff the method in the program class and all of that that's all behind the scenes it generates that for you you can just go ahead and add c-sharp code to the program.cs file and you don't have to have all that boilerplate code anymore this is very useful when you're doing something called minimal apis which is a very handy thing that you can that's becoming more and more popular for for Nano services or microservices or whatever you want to call them now C sharp 9 introduced a whole lot more patterns which is why pattern matching is going to be the next thing that we're going to look at it also introduced a Target type new expression that I also demonstrated and a whole lot more features that I personally haven't used and probably won't because they're targeting more lower level stuff in in c-sharp if you do that native sized integers and and function pointers and all of that very important things if you're working with I don't know unity game programming but personally I'm very fond of the other ones here so how about we we take some time to talk about pattern matching which is one of those important features that they've worked on from c-sharp 7 to 8 to 9 to 10 and 11. you'll you'll see that with all the newer versions of c-sharp there's going to be more patterns added and that's because they find new ways of being smarter about how to express ourselves pattern matching is all about being able to identify what something is does this puzzle piece have rounded Corners is it transparent what color is that thing how how many puzzle pieces are are there in this set can you give me the middle part can you give me the first and last piece there's so many things that we can express with pattern matching that sure we've been able to do it before with normal code or with link but being a first class citizen in the language means that it's a little bit nicer so I mentioned that we can use color matching in a whole variety of different ways it's mostly about matching on what type of object we're looking at and what kind of attributes that object has in terms of properties and values not the attributes that you smack on top of them using the square brackets but the attributes as in color name and so forth in c-sharp one through six you'd have to say something like this here so like if the type of this thing is my type of what I'm looking for and then I'd have to check a property if I'm looking for a specific color now this here is not really there's nothing wrong with this there's just a whole lot more characters to say something that I could probably Express a little bit easier especially if you've done kotlin or Swift this here is like 50 more characters than you have to to use so in C sharp seven they instead decided that why not require even more characters to express the same thing that's why I said that in C sharp 7 pattern matching wasn't really ready for anyone to use because even though they said the fundamental pieces in the compiler to make this work look at this part here case apple and then I captured this as a local variable app of Apple that I can use inside inside this case block here right so I can use that as the concrete type I don't have to type cast or anything like that which is quite smart but with c-sharp 8 and with C sharp 9 there was a couple of improvements that made this a lot more useful instead of having to say well I want to create a switch for this thing and then I have a lot of cases why not translate that or inverse that expression and use it more like how I would express myself when talking to a customer for example I want a result based on this input and inside this switch expression what which this thing is called this is the object we want to create patterns for so I wanted to produce a result which is normally from a method call you something that you concatenate something that you compute right so we want to get the result based on what kind of input we have we fill this with expression with Expressions much like expression body members the left hand side is the pattern in this case a very simple type pattern right with the expression and then I say this here produces a string doesn't have to be producing a string the only criteria here is that all of them produce the same type or at least the same base type so this here produces a string and the the final one here the underscore that's a discard it's saying that for everything that I haven't created a pattern for that's what you're going to do here right so that's when it's going to be returned from this pattern this looks simple and it really is but C sharp introduces a whole lot of patterns to make this even more powerful we just saw the type pattern on its own that's very simple I can say if this is on Apple if this is not null if this is null or whatever but we can also use it together with a deconstruct method to say whatever you deconstructed this to I want to match on the different values that you returned we can use it together with properties to match values on properties that we have we can match tuples or tuples or whatever your preference is we can have relational patterns to say hey I want to find all the people that are 35 years older or younger right so you can write patterns for that you can even build ranges to say hey I want to find everyone that's between these two age spans or I want to find the ones that have had a birthday yesterday or today right and you can group these different patterns together with parenthesized patterns you can negate them with a knot pattern all of these can be used together to create both very powerful expressions or powerful patterns that can also produce very unreadable code so you have to be very careful what all of these when used together they produce something called a recursive pattern right and what that means is that it looks first on exam for example a type and then we might want to look at a property so it starts looking at the type then it drills down and looks looks at more things on that before we jump back into Visual Studio let's just quickly list the important language features in in C sharp 10 because we're going to be looking at quite a few of these as well we have record structs Global using directives there's file scope namespace declarations there is extended property patterns so again there's improvements to pattern matching C sharp 10 was really mostly about improving what was already there it's not introducing anything groundbreaking like all the patterns in C sharp nine it's not introducing anything like asynchronous streams or the switch expression like c-sharp H does but it does introduce a couple of different language features that are interesting so how about we jump into Visual Studio and spend a bit of time looking at C sharp 9 and C sharp 10. let's start off by going to a different project and I'll show you I have this project here called pattern matching it has a class called test result or a file called test result it's using this record thing record is a way to create a reference type it's a another word of saying that this is a class it can actually be used together with the class keyword as well but by default a record is a class behind the scenes you could also have a record struct which was introduced in C sharp 10. depends on where you want this to be stored but a big difference between a record class and a record struct is that record structs or not read only you'd have to manually say that this is a read-only record struct and it becomes a little bit hard to understand and read so let's go back to the normal record and talk about what this actually is so this is a class why would I do this instead of just producing a class if we expand this a little bit here without looking at the body just imagine that you can't see that part this here is a primary Constructor it's defined together with what your class name is normally defined with so I say that the test result is built up of a number of attempts and which date you tested this on then we can have fields and properties and methods and all of that inside my record why would I do this if I can just use a normal class this using it for this sole purpose is not really it's it's intended purpose so I've created another record here actually I took the same one I pasted that into sharflab.io it's the exact same struct or record that we just looked at on the right hand side we can see all the decompiled code so what we get out of this here is that we get a class that implements I equatable it has read-only backing fields this here means that we have an init only property it's immutable record records are immutable by default which is what we want in a multi-threaded environment it has the Constructor it also has a generated method to get a string representation of this which is good for debugging or if you're logging so you can get this into logs very handy and then if we go down here we can see that it implements equality checks as well or records come with value-based equality so if you have two instances of a test result it doesn't care if it's the same instance if you compare two classes it will only do a reference comparison but with records it will compare each member it will compare the number of attempts with the test date right that's a very big difference but they also support adding methods and they also support inheritance as well I have a past test and I failed test that inherits from That Base Class very handy and here I've added a deconstruct method now records do come with a default deconstruct method that takes all the all the properties that you define in your primary Constructor and also creates a deconstruct method for that but here I've created my own one because I want to do some computation I'd like to be able to deconstruct a test result into saying give me the test date and give me how many days ago that was and I want to also indicate if it should be archived for example this could be whatever just to give you an example now to use it like that to to be able to then deconstruct this I've created a new instance of a test result I could then say well if my test result is able to be deconstructed into what I Define in this pattern here now notice here that this is where it does become a little bit confusing because there's no intellisense I I think I have to know exactly just tells me that there's no deconstruct that takes here or arguments so we have to know that the first one is test to date I don't care about the test date maybe I want to find tests that are 10 days older or older and I don't care about the last one this is extremely unreadable no one will understand this like if I go back to this code tomorrow I will have no idea what I wrote you can't use named arguments as well but since there's no help with intellisense it does become a little bit uh difficult to understand understand a better approach actually before I show you the better approach is that this here don't care if it's a test that's passed or failed it doesn't care about the subclass if I want to say that this can be a past test I have to specify that first right so now it has to be the exact type as well as being deconstructed into this thing I could also say I want this to be passed or I want this to be deconstructed into something like this here right so you can compose very very confusing patterns but it's also very powerful um as you'll as you'll soon see so we can change this up a little bit here instead of having to use the deconstruct method which is handy in some cases um especially if you match on all the different things that you get from your out method or your deconstruct method let's say that I instead want to say that I'd like to find where all the number of attempts or maybe I I don't have the the days here so I have to compute that myself but this here is using a property pattern it requires me to find a past test that also has this property set to a certain value so we can use this with normal if statements but we can also use this together with that switch expression let's say that I want to find the outcome based on my test result I want to produce a switch and in here I have to produce my or add my patterns now the final pattern is the the Discord that's the default thing that catches everything I could also say that I want to capture everything into a specific variable if I don't have that available or X for example and now X here would be available as a test result or a nullable test result because this may be null it catches both the object as well as if it's not and then we can add more patterns on top here so why don't I add the discard at the at the top same reason you don't do that for normal switches more granular on the top and the catch all at the bottom so we could say that I want to find all the past tests or I want to find I can't even spell or we want to find for example failed tests where the number of attempts is between let's say 10 and less than 20. I can then capture this as a if I can just do failed test right so why would I capture this as a local variable because now I could either pass it into a method call or I could use it inside here to produce a string so this here will in fact be a failed test it will be the actual instance that I can use in this case here right so this here shows the the type pattern it shows the the conjunctive and patterns I saw the show the or pattern at the top you can also have you know the parenthesis here and that would create one of these parenthesized patterns just to group it a little bit more nicely these are very powerful and you could of course also as I mentioned earlier you can use the not pattern to to negate an entire pattern that means that you cannot capture it because it has no clue what you're looking for even though the pattern works without a test case for this I have no idea what this code will actually find if we'll find all past tests that are not between 10 and 20. right it becomes a little bit confusing so be careful when you add this to your projects then not pattern is great in one particular case if test result is not no that is perfect that's a perfect opportunity to use that all right so that showed the the record types and the fact that they do have value-based equality so now if I do have if I created two instances test result one and two and we were to compare these two we know that test result is equal to if that is equal to test result two this would in fact go ahead and compare each property with each other now you would probably imagine that these would be equal but since I use daytime offset.now it includes the ticks so they will not be equal very confusing but just a little bit of a hint that I have a chorus on dates and times on pluralsights all right joking aside c-sharp 10 then introduced quite a whole bunch of features as well not as important as the ones we've looked at in c-sharp 8 and 9. record sucks is good record strikes is good if you want to store the struct on the Heap instead of the stack and the global using directives actually I didn't show you that the file scope namespaces default nowadays is that notice that I don't have to add any usings at the top except for my own namespaces here I don't have to do using system using system.link or anything like that it's because if you're going to the project file it has this thing called implicit usings enabled so it will bring in all of that for you it will just implicitly include things study things that you need and instead of having to wrap my entire file inside a namespace declaration we can say namespace at the top and this entire file now falls into that namespace which is also default when you create a new class in some cases and in some cases it's not Visual Studio tends to not be very um not do it similar for all cases but it's nice that's one of the things I go ahead and change as well just get rid of that indentation makes it easier when you code review so C sharp 10 as I mentioned in introduced quite a few things as well but not as groundbreaking as what we saw in c-sharp a tonight it did add something called constant interpolated strings which is what some people have been asking for as well so if you have a constant ring previously you couldn't use that with a big string interpolation one thing that was really good though is that in previous versions of c-sharp this here is C Sharp 9 you have to explicitly Define which delegate that you wanted if you did a Lambda like this here why would you have to do that when the compiler can just figure it out for you so in in C sharp 10 it can infer that for you so if it understands what you're trying to do we can infer the Lambda so you don't have to explicitly say the type here now I didn't mention earlier that this thing called top both top level statements as well as minimal apis this here is an example of a minimal API I have a and a app.map get so I can map a a specific path on a website to this thing here there's just like two or three more lines above this to create an actual web application and this is just a program.cs now in c-sharp 10 they added the the portion of your from header so you can have attributes in lambdas previously you couldn't do attributes in lambdas which made minimal apis like this here sometimes hard to work with because a lot of things in asp.net requires attributes so with about two minutes left let's go through c-sharp 11. there's quite a few things in C sharp 11 and I did mention that there's a talk tomorrow by David from Microsoft who's going to jump deep into C sharp 11. there's a few features added to c-sharp 11 that's that's great and some were removed due to com due to community backlash but to give you a little bit of a hint there's more patterns for example you can now look at a list to say I want to get the first part or last part you can slice off a little bit of a portion there's some changes to name off it's finally caching delegates for aesthetic method groups it's a little bit of a performance Improvement the required properties I showed you that it allows you to then say that a property is required when you create an instance of that we can have raw string literals which if you've ever done VB and you've done XML code inside VB it's pretty much the same thing it's amazing I I don't understand why it took so long um together with that static members and interfaces utf-8 string literals so you can say that hey I have this this string here it should actually end with u8 and that would be a utf-8 string and you would assign that to a span of byte why would you want to do that because all communication over the wire is mostly done in utf-8 so that would require less computation converting back and forth very good for performance and generic attributes this is one of the features that I've been wondering why they haven't added for a very long time as well the one feature that I did say that they removed due to company Community backlash is the null checking or the parameter and all checking if you added the double bangs on an input parameter on a method it would automatically do a null check and throw an exception if it was no which uh your code ended up having question marks all over the place because you had no reference exceptions or nullable reference types and then you had exclamation marks everywhere it just got really hard to read the code so with that being said there's quite a lot happening in c-sharp and I have a few courses on pluralsight on new things in C sharp 10 C sharp 11 12 coming next year or later this year so there's quite a lot of things to learn about the language I hope if you enjoyed this and learned a little bit about c-sharp and that you're excited to try some of these new features and as I mentioned earlier if you have any questions I'm here for the rest of the conference I'm available on Twitter and don't forget to vote on your way out and thank you so much for coming and listening to me
Info
Channel: NDC Conferences
Views: 5,978
Rating: undefined out of 5
Keywords: Filip Ekberg, C#, C# 8.0, C# 9.0, C# 10, Bugs, Developer, Code, NDC, Conferences, 2023, Live, Fun, London
Id: ys0DybCuhF0
Channel Id: undefined
Length: 60min 10sec (3610 seconds)
Published: Tue May 16 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.