 Hi, I'm Mass Torgerson and I'm the lead designer for C-Sharp. I want to welcome you to Microsoft Connect and share with you some of the major features that are coming into C-Sharp 8, the first of which you can actually try out in their preview that's come out at the time of this event. So I'm going to show, as many are in the preview, I'm going to show in Visual Studio. I'm going to head over there right now, and for the remainder, we'll take a quick tour and slides and they will show up in later previews and of course in the final product. So the first thing I want to talk about is Null, which has cost many an exception, a null reference exception in production code sometimes, and which we really want to do a better job in C-Sharp helping you avoid. So if you look at the code here, just a quick run through of the flow, I'm getting some subscribers, I'm getting the names of those subscribers through a helper method, which in turn is getting the name of each subscriber, which in turn is constructing a string based on the data, the strings that are inside of the person class that is in the subscribers collection. So let's just go ahead and run this code and I have some fun seeing all these nice names being printed out, and whoops, two came out, but now of course we have a null reference exception. The null reference exception, if we can scroll a little here, turns out that it is in that code producing the string, and of course it's the middle name that turns out to be null in the third person I was trying to render here, and therefore indexing into it leads to null reference exception. Well, wouldn't it have been nice if I had known ahead of time, not when my customer sent in this bug report. So that's exactly what nullable reference types are about as a feature. Essentially, nullable reference types are about solving the problem of finding out where nulls should be and where they shouldn't be, and tracking where they will be and won't be. So to make that concrete, let's start out by actually enabling the nullable reference types feature and I need to enable it. I can enable it for the whole project here, I'm just going to do it in source code, so you can turn it on and off. And the reason why it needs to be enabled, unlike all other C share of language features, is that it will give new warnings in existing code, and we don't want to do that to you when you upgrade, except when you opt into that. So you can see that when I type nullable enable here, I got a little green smudge here. That's a warning that showed up in my code because I enabled the new feature. So let's go and see what that warning is all about. It says that this constructor does not initialize the non-nullable property middle name. Well, non-nullable, what does that mean? Well, it means that when you turn this feature on, forevermore and C sharp, we consider your ordinary reference types to be non-nullable. We will stop letting you put null into them. So that seems a little harsh maybe, but it does ensure that you won't get that null later, so it might not be such a bad choice. So I'm not initializing it, maybe I could initialize it with null instead and make that warning go away. And indeed, this warning goes away, I'm now initializing it, but I get another warning saying, you can't put null into this, it's a non-nullable reference type. Well, what if I want my nulls? They're in the language for a reason, you can't just ban them. And sure enough, you can have nulls, but now you have to own up to it. You have to express, we're expressing here in a public API, yes, we will have nulls, beware here might be nulls, okay? So we've taken responsibility and told the rest of the world that nulls can be here. And now on the receiving end, the line of code up here that is trying to index into the middle name, now we get a warning here saying, oh, there's possible dereference of null. What can you do about that? Well, you can do what you always did. You can check for null before you dereference. So I can say if p.middleName is not equal to null, before I return that, and you see that the warning goes away. So essentially the compiler is tracking where it's tracking p.middleName here and anything else nullable and tracking where might it actually be null. And you just checked and saw that it wasn't null, so on this branch here, can't be null. And that goes regardless of how you check for null today, compiler is doing its best to track that and remove those warnings when it sees that you have actually checked properly and ensure there's no null in there. So another way that we could be doing this is that we could actually, we could do it as a conditional ternary expression, we could return that question mark this, copy and paste, put a colon. So bear with me as I reformat my code, but you can see now on the two branches of the conditional, one of them gets a warning and one doesn't, depending on whether the compiler sees that it might be null or not. And of course, on the one where it might be null, we'll just remove it from the result and return a string that doesn't make use of the middle name that isn't there. Okay, so that's nullable reference types. The next thing I wanna share is async streams. So in reality here, so I'm iterating over subscribers, I'm kind of imagining this as sort of a live thing, whenever somebody subscribes, I get the name as part of a stream and then I get them as part of a stream, then I get the name of that and I print that out. So this happens over time asynchronously. We're lacking a notion of async streams in C-sharp today and we're doing something about that and integrating that into the language. So let's say that I get an async version of subscribers and instead of being an inumerable now then, I async innumerable. That's like an innumerable, it can be for each. But it's one that's async, so you sometimes have to await the next element. And of course now I need to change get names to take an async innumerable and now for each won't work because you can't for each over async innumerables but you can't wait for each over them. So that's a little bit of new syntax that lets you for each over asynchronous streams. Of course I can only await if I'm inside of an async method but an async method can't return an inumerable. It has to return something async but that async thing can be another async innumerable. So now you're getting an asynchronous stream of the results here and if you look up here now I have to also await for each the result of this call and I can only await if I'm in an async method but I can make main methods async now as of C-sharp 7.2 and so now my code is back to working again and if we try running it, you can see that as these names trickle in over time, the results are produced and printed out and that for each loop is just sort of awaiting for every round with some delay and there we go, we've iterated the list that's produced and the program terminates. So that's async streams. The last feature I wanna show you directly in code, it's a tiny little one but we think it's gonna be very useful. Inside of my fake service here that I've been using all along I'm actually creating an array of people and then yielding that back out. Now, wouldn't it be nice if I could easily specify a subrange as slice if you will of that array and you can do that now with the range syntax so I can say I only wanna get from one to three out of this array and actually there's a syntax we're saying well I want one from the beginning and one from the end and then I'm sort of slicing off the out of most elements so the hat there means from end and that's the async, sorry, that's the ranges feature in C-sharp and that's pretty much it for the preview so let's go back to the slides and see some of the features that will show up in subsequent releases. So we saw this code here in the example before where I'm choosing between whether the middle name is null or not but actually the first name or the last name should probably also be able to be null. It's not always that people have first names or last names or maybe they have the names but they weren't recorded here or they didn't wanna give them or whatever. So we should expand this logic to more like a switch over all the different combinations and you can now do that using what we call recursive patterns. So I'm switching over a tuple of the three strings here and then in my case is I can put a pattern that also looks like a tuple. We call this a tuple pattern but inside of it it has other patterns which are then used to match against the elements of the tuple. So here I'm matching where they are non-null strings and here's the case for matching when the middle one is null. Of course we should also think about when the last name is the one that's null or when both are null or actually when the first name is null or there's actually eight different cases here and so your switch gets kinda clunky now and we've long felt that switch was a little long in the tooth in terms of being heavy syntactically so we decided now's the time to add switch expressions which is sort of a spiffed up version of switches that are an expression form. So here's that same code written with switch expressions. So the switch expression here is everything but the return and the semicolon. It has an expression. Then the switch keyword after that so it composes better with other expressions and then a list of cases that are just a pattern, an arrow and an expression for the result. And I think it kinda looks nice here that you can do these one-liners, you can do this tabular sort of layout and really see, you can sort of visually check that we handle all the cases here but beyond that actually because an expression has to produce a result, the compiler will actually check that you don't get to the end with some of the possible values not actually being handled so the compiler will give you a warning if you're missing some and if you ignore that warning, it'll generate code to throw an exception. An exception that says, well you ran out of the end of a switch expression, you can do that. So that's switch expressions. Tiny little but very neat little syntactic sugar feature. If I'm already saying up here that this array is an array of persons, why do I have to repeat the type every time? In general, when I'm in a context where the type is clear, why do I have to repeat myself? Say it's a big generic type or something when I knew up the object. Can't you just infer that? Well now we can. You don't have to specify these guys. You can just, when it's given from context that these should be persons, you can just write the new expressions like this. And then finally, default interface members are a feature that helps make it easier to evolve interfaces. Once you've published an interface, you're already locked in because if you add another member to it, your implementers will break. But we're now adding the ability to add members with, actually with a method body which is a little unusual for interfaces but it's going to be really useful because now existing implementers like console.log or down here, they can get that default implementation without having to change and therefore you've added that member without breaking them. Of course, new implementations will likely provide their own implementation. So this is mostly a feature just to make sure that you are compatible. That was everything. Have a great connect. Thank you very much.