 Hey, welcome back. For those of you who weren't here for the keynote, I'm Mass Torgerson and I'm the lead designer for the C-Sharp language. So the next hour, we're going to spend talking about some of the things that we recently added to C-Sharp and some of the things that we're planning to add, and hopefully there'll be time for a few questions from you guys as well. So when we look at the Stack Overflow Survey that goes out every year to developers, I always like to open that up and see how are we doing with C-Sharp. Here's the top many languages. I've sliced out the ones that I don't consider to be programming languages, and this is what you get. So if you look at the most popular programming languages, the ones that most people use, or at least most developers who respond it to the survey, you can see that C-Sharp is a prominently figured there. There's a lot of people using C-Sharp, and we're happy to note that more and more of them are using C-Sharp cross-platform on many different platforms. We also look at the most loved programming languages. This is where the smaller languages get to play because this is measured in terms of the percentage of users who would like to continue using that language. We're happy to see that C-Sharp is represented here as well. So we're in good shape in terms of both people using C-Sharp but also liking it and not just doing it because they have to. Sometimes it's interesting to look at some of the other languages that are on here. If you think about other languages that are on both of these top 10s, Python's been there along with C-Sharp for a couple years. Last year, TypeScript joined. So yay, go Microsoft. You also see F-Sharp down there is one of the most loved though it's not quite made the top 10 in terms of usage yet. This year, a couple more joined. The Swift language essentially has been loved for a while, now rose to higher usage and the JavaScript language. A lot of people are very happy with the JavaScript language now. So that was a little baffling to us. But I think that there's a common trend among many of these languages, which is that we all take quite an aggressive approach to evolution and making sure that there are all the tools in the box for people to use in professional development. So that leads us to, what is the strategy for C-Sharp actually? What are we thinking about? What are the goalposts that we use when we think about what to do with C-Sharp the language itself as well as the platform around it? There's actually a link here which you can go click that takes you to where we post our language strategy for C-Sharp Visual Basic and F-Sharp. So you can compare. I pulled out some of the main phrases here for C-Sharp, which is first and foremost, we'll keep growing C-Sharp. So whenever there are evolving needs, whenever there are new scenarios that we want to embrace, and whenever there's new technology or new ideas in the language space that would fit well into C-Sharp, we will completely embrace it, and we will also innovate aggressively ourselves. So we're not afraid to sometimes take the lead and introduce a new feature or a new kind of feature that other languages can then use to move their needle as well. So you've seen that several times over the years with C-Sharp. It's important for us to recognize that we have a very broad set of developers. We have great diversity in the developer base, and so therefore we have to focus our improvements mostly on things that benefit all developers or most developers. Sometimes they benefit them directly, and a few times they benefit them more indirectly, as you will see in the features I'm going to show later in this talk. Then last but definitely not least we'll continue to empower the ecosystem. In other words, to improve the influence and the dialogue that the broader C-Sharp community has on the evolution of the language itself. So this is clearly something that's evolved over the years. Now we're completely open sourced and if we get time, we can go and look a little at that as well later in the talk. The language to sign itself is open source, and there's a daily dialogue with the community rather than every two or three years when we would release a new version and hope that people liked it. So this has been a great trend for us, and that's something that we're quite determined to keep evolving that relationship with the community. That said, we also want to balance this with continuing what we think is one of the successes of C-Sharp, which is that we try to exercise very strong stewardship of the language and the design decisions so that there's one body of designers that have been in it for a long time and can guarantee continuity and coherence of the language as it evolves. So it's not a design by committee, democracy kind of design environment. There's still a little group of us that are making the ultimate decisions and making sure that all the people who are more interested in using C-Sharp and less interested in evolving it, that they get a solid experience going forward and they get a well-curated language if you will. So that's our mindset that we apply when we go into language design which we do several times a week. So here are the main phrases from there, keep growing C-Sharp, innovate aggressively, benefit all developers, empower the ecosystem and show strong stewardship. So let's talk about some of the recent and coming versions of C-Sharp. So over the last year and a bit, we released no less than three point releases of C-Sharp. That's a new thing for us to have point releases. We usually have major releases every couple of years that have major numbers like something.o. In fact, when we got to six, we figured we were never going to have anything but .o releases and we started talking about it just as C-Sharp six, not C-Sharp 6.0. But with seven, that changed. We realized that we had evolved so much in our process, that we were able to ship more often. And also, we didn't want to hold back value that developers could get sooner if they wanted to. While at the same time recognizing that smaller steps maybe shouldn't be something that everyone was forced to use. So we reintroduced this divide between major and minor versions. We also had some specific scenarios that span across all of the .net layers, if you will, that were related to framework and runtime work as well as language work. And we wanted to ship those as a package. And so this was a good time to exercise doing sort of out of band releases of C-Sharp, if you will. So that's what C-Sharp 7.1, 7.2, and 7.3 were about. More specifically, the sort of core, there are a couple of like driving themes here. The core driving theme is one about safe, efficient code. So this is a feature set that is primarily targeted at people doing somewhat lower level programming in C-Sharp. So they're sort of the direct beneficiaries, if you will. But because they're building the lower levels of what everyone else builds on, there's direct benefit certainly in terms of the improved performance that those frameworks can get. But sometimes also the abstractions that they can offer are better because of these features. So it's something that has a positive impact on everyone, even though many people don't need to relate to it so much. So we'll spend our time talking about 7.1.2.3 here, primarily focusing on these safe, efficient features. And I'll show some demos. I did a short one in the keynote earlier this morning, if you saw that, but there were various AV difficulties there. So I'll try to get that whole demo flow a little more expanded this time and show all those features. They're also just general improvements, things that used to be not allowed, that are now allowed, such as using delegate or enum as constraint, as constraints and generics and many more things. And they're also the usual set of nice abbreviations that let you write things shorter than you used to. So I have a link at the end of the deck where you can go and look at our docs at docsomicrosoft.com and they generally have very good, but they do have very good summaries of what's new in the individual versions and so on. I encourage you to go and look at all the things I don't explain here, or even the ones I do and kind of get the details on it. So then there's C-Sharp 8, which is our next planned version that's coming up sometime later. And the main theme here is for it just to be magical. Like this is where we wanna do, actually a not very tightly related set of features that all are bigger and have more of an impact on how you program and hopefully take your development to a new level. So I allowed myself one unicorn today here and this is it. So before we dive into that though, let's take that thorough look at C-Sharp 7.1, 7.2 and 7.3. So let me go into Visual Studio and start out with this particular project here. So I wanna talk about the improvements we made around REF, so some of you may have noticed there's a REF keyword in the language, you probably don't use it very much, but I'm gonna show how several improvements and new things here can make working with structs a lot easier and a lot safer, like give you a lot of places where you don't need to reach for unsafe code, for instance, and pointers. And then building on that, we'll talk about the new span of T features in a minute. So REF is really a feature for passing things by reference and since objects are already passed by reference, like you never copy an object to somewhere else, you always just pass a reference to it. This is primarily interesting for structs, so if you're trying to improve your performance and void allocations by using structs, then you'll wanna use these features and if you don't, because you were at a higher level, then be thankful that somebody further down are doing it, like the improvements you saw in a Tekken Power benchmark, for instance, in the keynote, those derive among many other things from starting to adopt these features here. So just as a reminder, I have a little program here that has a method that takes two ints and returns an int, which is one of the two that it got in and then mutates them and writes a few things out. And let's do this by REF instead of passing the ints by value, we'll now pass REFs to the ints. So you see that when I put the REF modifier on the method here, I get a squiggle down here saying I'm asking for parameters by REF, but I'm not passing them by REF. So the arguments also in C-sharp, ever since C-sharp 1, 0, have to have a REF modifier saying, hey, you're not passing the value that's in A and B, you're passing the actual variable A and B and you're passing it to someone so that they can change it and modify the variables that you declared here and that you see, okay? So that's been around for a long time. Now one of the, let me just look at my cheat sheet here. Yes, so one of the things that you haven't been able to do is to use extension methods where this parameter, the first, the receiver of the extension method was a REF, so that's something that we added recently. So you can now say this here and then you get an extension method that if I choose, I can go and call it with A as a receiver and now I need to remove the first argument and I'm passing it with A here instead. So you see in this case where I'm calling as a receiver, I don't have to say REF for the usage of A here and we think that's all right because when you're calling things as an instance method, you're kind of expecting that to be able to mutate the receiver. So we think that sort of the visual cue is good enough without having to sort of massage the REF keyword into the syntax here somewhere. So that's extension methods. Another thing that we wanted to improve was using REFs without fear. Okay, so I talked about this fear inducing step of passing your actual variable to someone else who might mutate it, which is the case here. They actually do mutate it. But what if I want to pass, let's say it's not int, but it's a big struct. I want to pass it by REF for efficiency's sake, but I don't actually want them to mutate it. That's something that we then went and added new features for in C-sharp 7.2. So instead of a REF parameter, let's say we want, for why here we want to protect it against a mutation, I can pass it as an in parameter and now that means that still passed by reference, but you can see the method is no longer allowed to mutate it. So the mutation of it is forbidden and that means that the method here or the main method here can safely pass it. So I'm going to, so I don't get to use the REF keyword anymore because I'm now passing it by in, so to speak. So I can use the in keyword instead, still matching that doing the keyword match here. And that means I acknowledge that they can see whatever changes I make to be, but they can't make any changes themselves. Now that looks an awful lot like passing things by value, except that it's more efficient and so we actually do allow you to not even say the in keyword. You don't need to be warned in syntax that you are passing something by in because the people you're passing it to won't be able to do anything with it. So you can actually omit the in keyword altogether and pass just the variable like that. And in fact, if you do that, you can even pass something that's not a variable like 40 or let's just use 42 here and we will automatically create a variable in the background and pass it by as a read-only REF to the method. So that's in parameters. Now a thing that we introduced a little while back is REF returns. So I actually want this method not just to return the value of one of the variables but to actually select one of the variables and return the variable itself. So I can do that by returning by REF. Okay, so now I'm returning either, in this case I'm returning X by REF and I have to acknowledge that by returning the REF to the X variable here. And that's fine, but here I'm still, so I'm returning it by REF, but I'm still taking the value and putting it into the C variable here. If I want the REF itself, the reference to the variable, I have to sort of take the REF like I do when I pass a REF parameter and then I have to declare the variable as being a REF as well. So now C is no longer a variable holding an int but it's a variable pointing to another variable holding an int, right? And which variable that is, that comes from the REF initializer here which is whatever comes back from the or maybe method. So in this case, you can see since it returns a REF to its X parameter which we passed the A variable for that, then C will actually be an alias to the A variable. And so when I increase it here, we can try running it, when I increase the variable here, you can see that the A variable changes as well. So there you go, you can see that A and C are aliases to the same variable here. So in general, you have this idea that a REF is sort of like a window onto another variable. You have some storage and you have a window onto the storage. And if you use in instead of REF, the window is closed. You can see through it but you can't reach through it and manipulate the thing. So there's this open window and closed window analogy that we can exploit a little further down the line here. You can also actually make the thing that comes back from a method read only. So I could return a REF read only to int here and that makes the caller not able to mutate the variable that they get back. So here we get an error because I am storing it as a REF and then mutating it but I have to store it as a REF read only to promise that I won't mutate it before the method call will let me grab that REF and hold onto it. And now I said I can't mutate it and so I get a squiggle here when I try to do it anyway and I have to stop doing that. And the nice thing about that is that if I didn't have read only here, so let's just remove that for a second and if I pass the X parameter by in, now I have X as a read only thing and so I'm not allowed to return it by, to return its REF to someone who might mutate it and in order to keep the contract, the thing I promised here by saying int to X I have to also make it read only when I return it back out again in order for the squiggle there to go away and then I can't mutate that one either. So you see how it all hangs together? The extra protection of int and of read only kind of flows through the whole thing and guarantees that you only mutate things that you want to. Now that was a whole lot about REF and why is that interesting? Well part of why it's interesting is that in a subtle way REF and REF read only are part of the span of T story that was this framework runtime and language feature set that we rolled out recently and that is part of C-sharp 72 and 73. So let's go and have a look at span. Span is kind of like REF but for whole arrays for contiguous memory if you will. So where a REF is a window onto a single variable a span is a window onto a whole array or like a chunk of an array and let's see that in action here. So I have a program here where I create an array, I initialize it and I write out all the elements. So let's go and try to play with span in this program and this is the demo that didn't work out so well in the keynote this morning and hopefully it works out better today. So if we go and look at array you can see there are a couple of new extension methods. One of them is as span which lets me get a span from the array, whatever that means. So as span return to span of int let's grab that span of int into a variable call it span and now what we have is essentially an alias for the array. It's a window onto the same elements and we can see that by writing out the elements in the span instead of the ones in the array and you should be able to still see the initialized values here from zero to nine even though I took the span if you will before I initialize the array. So if the span had copied over values it will still be all zeros. If you want to further assure yourself of it we can also turn it around and actually initialize through the span and write out the elements of the array and you can see by initializing through the span I'm reaching through the window and manipulating the array that the span points to that it's an open window too if you will. And just like let's get to that in a second well let's get to that in a second but one of the things that you might want to think about is what can you then do with a span? Well you can do many of the same things that you can do with an array but you can also do other things and one of the things you can do is that you can slice them. So I can take a slice of a span for instance from the third element and five elements on from there and what that returns me is another span that's only to part of the array. So it's still to some of the same memory locations but with some of them sliced out and so if I write out the elements of the slice here you can see that I only get the ones from three to seven which are the ones that I sliced out. But I'm still looking at the elements that only got initialized after I created the slice so still no copying of the array here. And we can also modify through a slice so I could do slice of two equals 42 and then actually write out the elements in the span and you can see that I modified the one that was the second element from the slices point of view but which is actually the fifth element or sixth element depending on how you count of the underlying array and the span that I created this slice from. So it all kind of works out windows onto the same memory and you can imagine how you can manipulate these in various ways and have nice method signatures that pass refs and spans around without copying. The thing that's kind of missing here still that was in the ref story is if I pass a span to someone how can I prevent them from modifying the thing that the span refers to and similar to ref read onlys there's a read only span type that you can just convert your span to and that prevents modification. So you can see that if I make the slice read only span and I don't get to reach through the window and manipulate it. All right, so that's the deal with span here. There's one C sharp eight feature that I'm actually gonna, that I can't show you today. We have shown it before but the bits are currently in a state where I can't demo it but it's going to be quite interesting in connection with this as well as many other things. And that is that indexing in C sharp is kind of basic. You can pass like for instance to an array. You can or a span here. You can pass an int and you get that number element. One thing you can't do is for instance say I want the third element from last. You have to do your own math in order to compute based on the length, the current length of the array of the span. You have to compute the third element from last. So we're introducing a little syntax to do that. It's not gonna work here but I'm gonna type it anyway. So we use the little hat symbol to say from end essentially. And that's useful in and of itself but one of the things that we then also wanna use it for is to introduce a notion of ranges into the syntax of C sharp. And one of the places where that'll come in really neat is for instance for the slicing operator here instead of having to call a method and giving these parameters. Well, we could just index the span with the range from say three to seven, three dot dot seven or the one I had there was three dot dot eight or maybe three dot dot the third from last or whichever combination of the indexing and range syntaxes you want here. And the ranges are also planned to be open ended optionally. So you can say three dot dot from three to the end or you can say from the beginning to seven or you can actually just say all of it. So there's a range that's open on both sides. It just means get me the whole thing. Which is something that you might wanna do if you were for instance slicing on multiple dimensions and some of them you don't wanna narrow in and so it's a convenient syntax to not have any of the end points visible here. So that's something that we have a prototype of and it's going into C sharp eight. But from here I wanna go back to, I wanna go over to another demo and sort of move firmly into things that we're doing in C sharp eight. That's a demo of the nullable reference types features that we're adding and then after that we'll see some slides of other features that are planned to go into C sharp eight right after I type my password here. So now you can get to see how long my password is. There we go. Luckily I didn't need two factor authorization here. It would have taken a while. So here is a, this is on a remote machine and that's because the bits aren't working on my machine right now. But this is an example of a program that looks completely innocent and innocuous but it's actually dangerous. And this is, if you go through the program here you can say I have a person with a first name and a last name it's Miguel. I get his middle name and I write it out. And the method that gets a middle name does exactly what you'd expect. It gets the middle name and gets the length. Okay, so that looks fine and there are no flashing warning signs but if I compile and run it then you probably won't be surprised because you're probably as scarred as I am that you will, well once we're done compiling we won't actually get the length of Miguel's non-existing middle name, we'll get a runtime exception. That's a null reference exception. And that's something that we've gotten so used to but it's still very hard to keep the null reference exceptions out of our production code because we don't have proper tools at development time to kind of minimize the situations where we accidentally run into a null. This kind of situation is a little hard because it's unclear who's to blame here. Is it the method here to blame for getting the length of the middle name or is the constructor to blame for putting a null in there in the first place? Who decides what the contract is? Should a middle name, should a property be able to be null or not? So that's where we figured it's time for some more expressiveness and C sharp and to have a feature that helps you deal with that. And so let's go and look at that person class and start from there. There's a new feature in town. It gives you extra warning so you kind of have to turn it on and that feature is nullable reference types. So in order to turn that on I use an attribute here. So at the module level, I'll specify the attribute non-null types. And that attribute, what it says is that with this attribute we're gonna start considering all your reference types to be non-nullable. And we're gonna warn you if we see you sticking nulls in them, okay? So we are strengthening the contract around all the reference types that are in your code today saying from now on we're not gonna let them be null any longer. We're not gonna give you errors so we're gonna give you warnings to help you not do that. So obviously that can only be part of the story but it's a pretty useful part of the story and we'll get to the other half in a little bit. So what you see now that I have that turned on I get a warning on the person constructor here that only initializes the first and last name and the warning says you are not initializing the non-nullable property middle name. You are not making it not null. Well I can go and fix that warning real quick I can initialize it a middle name equals null now I don't get the warning anymore but I get another warning saying hey you can't put a null in there either you can't leave a null and you can't put a null. Well what can I do then? This is the other half of the story well I can declare to the world that it is supposed to be null, okay? So I can put a question mark on the string type on this reference type just like you already can with value types and that is how I declare that the middle name is in fact a nullable it's supposed to sometimes be null and whoever consumes it better take that into account. They can't trust it to be there the way that first name and last name can be trusted because I always initialize those. So now you see the warning went away on the initialization here and even if I didn't have the initialization I wouldn't get the warning on the constructor because it only cares if the non-nullable reference fields are initialized. So far so good. I owned up to my nullability in the surface area of the type that I'm using. How can I then make use of that when I consume it? Well, you see another warning here saying hey you are possibly dereferencing a null reference here p.midlame might be null yet you're dot lengthing it. You shouldn't be doing that. Well I guess they're right, okay. Since the surface area of the type that I'm consuming has now been detailed to specify the nullability I no longer have any excuse here when I'm consuming it. I can't be in doubt as to whether I need to handle nulls or not in any given case. Fact of the matter is first names I don't need to handle nulls, middle names I do. The signature says so. And so now it's on me to fix this bug. Now we didn't wanna add new fancy features to C-sharp for fixing this bug. Like we wanted to be able to recognize the ways that you already checked for null today. So it should be that if you write null safe code the way you've always done it then we will recognize that and we won't give you warnings. And so that kind of leads us to introducing this feature of a flow analysis that will try to track the value of different variables and properties and throughout the flow of a method. And we'll try to see where they can possibly be null and where they can't and where they can't possibly be null we won't give you warnings on a de-reference. So let's put that to the test. So literally a test here. I'm gonna say if Peter, this is one of the ways that I might fix it. If Peter middle name is null remember always use an is not double equals for null tests unless you're absolutely certain that there's no user defined override of the equals operator. Better to use is it always does a null check properly. Now, if it's null then return something else let's say zero, let's say that's the default value. And now you see the warnings go away because the compiler can see that if you ever get here then Peter middle name clearly wasn't null. So this is one way of fixing it but either way you try will have the same effect. If we move that and instead we say, I mean if you put the if in front here and invert the condition that will work too but let's try some more creative ones. Let's use question dot for instance. Let's only do the de-reference if the thing is not null. Well now we get a different error saying that we are not returning the right type because that makes it nullable. So I guess we could go and return the null to the caller and then you can see it's up to them to deal with now we're in the nullable value type space here and it's up to them to deal with the fact that the length might be null. But if we wanna keep it in the family here keep it inside of the method then another thing I could do another thing I could do is to use the null call lessing operator and saying, hey if the left hand is null then use zero instead. And now boom all the warnings go away and I have an int that's either zero if the thing was null or that's the length if the thing was not null. And again, the compiler is tracking all the conditional logic here and making sure that hey you're not de-referencing anywhere that you don't know the thing to be not null. So that's the core of the feature. The combination of the ability to specify your intent is it null, is it supposed to be null or is it never supposed to be null? So you specify that by having a question mark or not on your reference type and then combine that with the ability to check the usage of everything that's declared in that way and making sure that you use it according to the declared intent. You get a warning if you put a null in where you're not supposed to you get a warning if you de-reference something that is not known not to be null. That might be null, okay? So and as you saw this because this feature adds new warnings we need to make it opt in in some form because we can't just like ship a new version of C-sharp and all of a sudden you start getting new warnings. That's a breaking change and people really do not like breaking changes and we've been avoiding them so far. So let's keep doing that. And so you have to explicitly opt in by somewhere in your assembly specifying the module level attribute non-null types. You can actually, the attribute is a little more granular than that and if you have like say, let's say you have a gigantic library, lots of public surface area and you kind of want to go gradually opting into the whole reference type is non-null default on a class by class basis for instance. You can put this attribute more granularly on a class or even on a method and you can even give it a false argument to opt out for a certain scope of code and that way sort of in a transition period you don't have to sort of own the whole nullability problem for all of your code at the same time you can gradually roll into it. So that's something we're sort of finishing the design of right now and there are also sometimes methods don't have like clear nullability behavior. Sometimes they have special behavior with respect to null. For instance, you know the is null or empty method on string well it actually guarantees that if it returns false and the thing isn't null but there's no way the compiler can know that by looking from the outside and so we're also fiddling with special attributes so you can put on special methods and further detail their null behavior tell let them tell you extra things about what comes in and what comes out. So that's all still in the works for when this ships in t-sharp 8. So that's null reference types that's the feature that is most done and also we think it's a very potent feature and we're looking very much forward to rolling it out. So now let's go back to slides and look at some of the other features that we're planning for t-sharp 8 and then have a little time for questions at the end here. So if we hop in here and go and project that. Another feature that we're quite excited about is the ability to better evolve interfaces. So the feature is called default interface members. One of the problems with interfaces is that you can never add a new member to an interface because all the existing implementers will then be broken. They won't be implementing the new member. So once you have an interface and it's published you're kind of stuck with it and that's a little harsh. So we wanna introduce a way that you can soften that up a little bit and that's what default interface members are for. So in this case here for instance I wanna introduce another overload of the log method on the interface so that people have the option of implementing that more efficiently for instance or with different semantics. And the way I get to do that without breaking existing adopters of the interface or existing implementers is that I specify a default implementation. So there's a default implementation here in terms of a method body that uses the other members on the interface to implement some sort of default behavior. And then my existing console logger they're not affected at all. In fact, we're gonna put this into the runtime so that they don't even have to be recompiled. They will just automatically get the new member with the default implementation when seen from an assembly that knows about the new member. So the runtime makes sure it's there. On the other hand though the member can of course be implemented then the default implementation just doesn't play in at all. So here we're explicitly adding an implementation of that interface member and you just never knew there wasn't in that case you never knew there wasn't a default implementation. So we think that's a good feature for softening up the evolution of interfaces. And also maybe I think you might think about assigning your interfaces a little differently offering a few more methods maybe than you usually would because you don't have to be quite a sparse. You can offer more members that have sort of default implementations and it's still as easy for implementers to implement the remaining behaviors. So that's that one. Another thing that we've been looking at for a while is that there's sort of a hole in our story around async if you will. We introduced async to the language in C-sharp five and there's a notion there in the framework of a task of T, a task of int for instance, task of string, which is essentially an asynchronous result. It's something that you can await and then at some point in the future it will produce a single value that then the await language feature lets you consume right there and continue your code from where you left it when you decided to await that thing earlier. But it only works for single values and a lot of what happens asynchronously these days is actually more like asynchronous streaming. So you have a continuous stream of data either like a limited one that just comes in multiple chunks for efficiency over the wire or maybe a stream from an IoT device or something that will continue to give you values at a given interval or random. And you need better ways to consume that as well. And so we want to support a notion of asynchronous streams essentially an asynchronous version of I enumerable which is something that can be for each. So we're introducing I async enumerable and you can for each await those. So there's a new version of for each that will consume I async enumerables and automatically for an asynchronous stream automatically halt the loop until the next value is available in an asynchronous manner inside of an async method. We're also not shown here but we're also going to update iterators these things that can produce I enumerables today by doing yield return. We're going to also make a version of that that can produce I async enumerables in the same manner. So language support for these asynchronous streams and then as a sort of very related point another thing that you can't do asynchronously today is disposal. You have the I disposable interface and it forces you to have a synchronous dispose method. Well what if disposal includes like closing a file or something that's inherently async and you want when you have a using clause you want to wait after the using clause ends you want to wait for that all to have happened. You want to know that disposal is complete. It's not a really good mechanism for that today. So we're going to also introduce I async disposable as an interface and using await as a mechanism to consume an asynchronously disposable object and it'll work exactly the same way. It awaits the disposal. There's going to be a dispose async method in there somewhere. It awaits that at the end of the using. So that the next line after won't be executed until that all that asynchronous disposal has happened. So that's the async story that we're looking at and there's still questions in there around how far do we go with async link and stuff like that on top of the async in a mobile. That's all being worked out also for C sharp eight. And again this all happens in the open. You can go and see the state of the implementations. You can go and see the state of the discussion the length sign notes and so on online. Another feature that was a really good start I think and kind of covered the 80% scenario in C sharp seven but could definitely be refined is pattern matching. So we introduced patterns in C sharp seven. There are more things you could definitely do with them. Patterns today can either be used in an is expression or they can be used in a good old fashioned switch statement. Well a switch statement is great. It lets you go through all the options one by one but syntactically it's a bit of a bear. It's like 50 year old syntax from C that has been carefully carried over from a language to language and so it's kind of clunky. And one of the things we wanna do is introduce a switch expression. That's just sort of like the Zibi version of that that doesn't have all that syntactic goo and this is roughly what it's going to look like. So the expression form switches an infix operator between O the object that I'm gonna switch on and then a bunch of cases here which don't have the case keyword cause that's fluff. They just have a pattern followed by a lambda arrow followed by the expression for what is the, what are we going to produce out of the whole expression if this pattern matches. So we just go through an order like in a switch statement is it an int then call it I and return this string here is it a point then here is another thing that we wanna improve with patterns which is recursive patterns. If it's a point then deconstruct a point according to its deconstructor which again a feature we add in C sharp seven and then apply these nested patterns recursively to the values that came out of deconstructing that point. So point comes in, we deconstruct it, we get two values. If they're both ints then they satisfy this pattern and then call them X and Y and X and Y can then be used in the expression that produces the result of the pattern and so on. And of course there's a discard that you can also use and that means you don't need the default keyword in here either. So that's one thing or rather two things the match expressions or switch expressions and the recursive patterns there. And then a sort of special version of the recursive pattern that I think is gonna be quite useful. I don't know why I have the match keyword there that's just a slight copy paste fail. But switching on tuples and being able to match with tuple patterns here as well. So that takes us pretty much to the end. There's the C sharp lang repo is where all the language design discussion happens. We can go and take a quick look at it in a minute. There's a wiki there where sometimes there are links to prototypes. They don't quite work with current versions of Visual Studio right now but we update them from time to time and then you can try some of the very early versions of the features of ones that we're like still tinkering with. But also participate in the language design discussion and so on. And the docs that I mentioned before docs.microsoft.com has brilliant docs for C sharp that follow along the new versions very quickly. In particular, if you go to the watch new on the C sharp you get the latest versions and all the features that are in there. So I want to just quickly before we take it over to Q and A just show you that GitHub site the C sharp lang site here. So this is where language design happens. The documents that we use for designing C sharp are all kept here in the open where everybody can see them and the discussion is here in the issues where everybody can participate. So you can see the source code in this repo is actually documents. Here are all the meeting notes from all the C sharp language design meetings dating all the way back to 2013. If we go into 2018 you can see there's some pretty recent ones down here. Here's the one from September 5th and you can just go and see what did we discuss and you can go and have an opinion about it. If you go to the issues there are various things to look out for unless generally there's a lot of discussions in here but we also track features to milestones in here. If you look for the label that is proposal champion that means that this is a proposal that someone on the language design team thinks that we should look into. And so that's a really good label to filter forward to see what is currently being considered by the C sharp language design team. And if you then wonder about well what's the current timeframe for considering it you can go and further you can go and look at the milestones that are C sharp versions essentially. So for instance the things that are currently considered we're going into C sharp 8, C sharp 8.0 are these ones here. And not all of them are gonna happen like we generally have a lot more in these milestones than we'll actually end up shipping and that's the milestone is more like an indicator of when do we think it's a good time to have the discussion and make a decision. And then the decision might be we actually don't wanna do this or we'll do it later then we change the milestone and so on. So that's just to that community aspect of C sharp language design and giving you sort of inviting you in here for the many of you that have never gone there come in and have a look you don't need to be a language wonk and you don't need to participate in all the heated discussions you can quickly get sort of just an impression of what's going on in there and I really recommend that you do that. And with that let's go over to the Q and A I think we have another nine minutes or so for Q and A so I'm going to see what's up on the screen up here and then take some questions. So here's one, are there any new C sharp capabilities especially useful for data science? That's a really good one. This data science in general machine learning in particular which you know some would say is a particular branch of data science. That's something that we have generally not been good at in C sharp and in .NET we're rapidly getting better. If you heard the keynote you heard about ML.NET where we're going very actively after having great machine learning frameworks in .NET. And so how does C sharp stack up here? Well, it has a few things from old that's operator overloading for instance but in general it's not very good and so there are definitely things that we're looking at doing. One thing that's particularly good for large data sets is the range and index features I showed before. They're going to make it much easier to manipulate those large chunks of data together with span and everything that's already in there. There's also things that we're considering but that are particularly difficult because they will need significant runtime changes as well. One of the things that's hard in almost all programming languages is a good type safe way to abstract over numerics. I wanna write in a generic algorithm that works for everything that has a plus and a zero static property for instance. How can you write a generic constraint that says something that has a plus and a zero property, a static zero property? Well, we don't have that today and we're looking into various ways of providing good numeric abstraction maybe through allowing interfaces to have static members and operators or things like that. But that's probably on a slightly longer track but that's just a few of the things that we can definitely do better at the language level. Also, we can always improve computation speed looking at targeting GPUs and so on and that's all work that we're looking at. Hopefully you'll see us move on over the next couple of years in a big way. Okay, Igor asks, will we ever get a bit more verbose null reference exception that will include information about what variable was actually null? Well, if you use the debugger in Visual Studio it will tell you exactly what variable was null. So we did that as an IDE feature that will tell you right things as long as you were inside of the framework of Visual Studio. Now, couldn't we do this at runtime even when you get those null reference exceptions in production? Well, that's much harder because now we're talking about information that's not actually stored anywhere and we would have to store a lot of extra information in those lean mean production and assemblies in order to get that. So I don't know that we'll get that but as long as you do it in the debugger in Visual Studio you got that. Okay, what can you tell us about the async streams feature? Also, so I pretty much told you what I could. How does it relate to the reactive streams work being done in the community? So that's a really good question. So for those people who aren't familiar with reactive streams, the idea of reactive, well, the idea of an IA-sync innumerable is that there are pull collections. You get a new element when you ask for it. So you pull for elements. Reactive is a push kind of framework where you give your collection a callback and it will call the callback back whenever there's a new element. So it's pushing information to the callback and that's sort of two opposites and it affects the direction that you compose them in, if you will. So pull has the problem that consumption needs to happen at the speed of the consumer. So somehow the producer needs to make values available when you're ready for that. Async is better because it's a little better there because the consumer is at least willing to wait around until the value is there asynchronously. Push has the opposite problem that it happens at the speed of the producer and the stream of values might easily choke consumers that they just can't process the values coming at them fast enough. And so you can make, you could also in parallel have an async reactive framework that would kind of hold back the producer. But here's the thing, there's an asymmetry where there's oftentimes one producer but many consumers and so should one consumer hold the producer back so that the, and thereby slow down the other consumers. There's a difficult problem there but I think that the two can be adapted between quite well through framework. So if you have something that's reactive and that produces values, we can build adapter types that turn those into asynchronous streams that you can then, depending on what adapter you choose, your consumption experience can either buffer any elements that are produced in the meantime or the last N or you can keep just the last value or not even that, it can just asynchronously wait for the next value to come around whenever you look around. So I think there's a way to deal with that. Okay, one more question here. Will the end of collection operator, the hat operator work as a reverse index or count from end? In other words, to get the last element in an array, will I use my array hat zero or my array hat one? The answer is you'll use my array hat one. So it essentially does work like, as if you set count minus the number and count minus zero is count and that's off the end of an array. Where you would use hat zero is as the endpoint of a range expression because the range is exclusive at the end. So hat zero would point correctly to the element after the last one. So that's where you would see hat zero being used. And that's one of the reasons why we didn't go with minus or something like that because then you'd want to be able to distinguish zero and minus zero and those are really hard to distinguish. That's pretty much it for time, I think, and there are no more questions up there. So at least that I can see on the screen. So with that, I want to say thank you very much for listening in, either live or at the leisure of your own time and go play with the latest C-sharp features, keep an eye out for C-sharp eight and try the previews as soon as they come out and tell us what you think. Tell us online because we're there and we're eager to hear and hear your feedback. Thank you very much.