字幕列表 影片播放 列印英文字幕 - Okay, welcome, welcome. I hope you're sitting comfortably. My name is Mads Torgersen, and known in America as Mads Torgersen. I work on C# for Microsoft. I'm getting old, so I always carry a t-shirt with the name of the program and language I'm working on in case I forget. And I'm here to talk about C#, and why it may be worth thinking about, even if you haven't so far. So let's get the embarrassing details over with. How many people are already familiar with C#? (laughs) That's a lot. How many are not? Wow. So I will completely fail, introducing somebody to C# at this talk. Good to know. We can maybe breeze over some details I had planned on, and get into some I hadn't. So, even so, they say that the reason why they make those SUV commercials, is not to make people buy them. It's to make the people who already bought them feel good about the fact that they did. So maybe I can achieve that. So, I have been asked to remind you to evaluate the talk. It's good for me, because then if I do something in an unsatisfactory way, I can do it better next time, maybe. And it's good for the GoTo folks, because then they can decide whether to invite me again some other time. So this is in the feel-good department. Stack Overflow have a survey every year of their developers, and they ask them various questions, and, of course, it's skewed, and unscientific in all kinds of ways. First of all, you have to be on Stack Overflow to participate, but I like the numbers, so I'm gonna use them anyway. So if we look here, C# is a very widely used language. It's number four here, of the three above, one of them is not a programming language. So I'm not talking about JavaScript. I'm talking about SQL. So C# is definitely a language that's in broad usage already. It's one of the, sort of, main mainstream languages, if you will. And they also ask people whether they would like to continue using the language they're using, and they use that to rate the most loved technologies. And it's interesting to see that C# is on this list as well. So people actually love C#, to some degree. There are some languages that they love more, but if you notice, many of them are languages with smaller audiences, sort of very dedicated audiences that are maybe more part of a cult or something. But it's only a few here at the bottom that are actually in both lists, that are both highly used and highly loved. So it's nice to be one of the three technologies on that list, two of which are programming languages, and yay for Python also for being on there. Right so, we and Python, we must be doing something right. And we constantly try to think about, what is it that we're probably doing right, that we have still fairly enjoyed programming language after all these years. So it seems to be not the fact that everybody uses to C# just because they have to, because people did 10 years ago at their company, and they have all this legacy code. There seems to be some kind of energy around, and we wanna try to keep that going. And we have some ideas about why that may be, and that's sort of what is driving our language evolution, if you will. So we'll get back to that a little bit later. But I think one core thing to point out here is that we are very eager to evolve C#. Like if you look at the language evolution scale from a little to a lot, we are kind of over there. As mainstream languages go, we kind of tend to be pretty aggressive about keeping the language fresh, and keeping it modern. And as the programming language state of the art evolves, so do we. And sometimes we are the movers, and sometimes we are the followers, but we try to keep the language a good choice for programmers in modern day. Not just something you have to do because somebody made that choice in a previous decade. So that's kind of our philosophy around it. I also wanna point out F#, because it's our little sister language, and it's very popular, because it's also very small. And there's a talk next door about it at the same time. So I'm sorry that those are scheduled at the same time. But F# is a very much more functional language, and we have a lot of benefit from the collaboration with F#, and the kind of inspiration that it gives us in the C# language design as well. So I wanted to call that out. So how many of you use C# on something other than Windows? Okay, thank you. It looked like none for a second there, now it's more like two percent. Good. That's a lot. So most people use C# on Windows, and that's because that pretty much used to be where you could use C#. And we kind of are changing our tune on that. So part of the reason I wanted to frame the talk in this way was that we're really pushing. It's sort of increasingly been the case, that you can use C# elsewhere, but we're pushing to make that an option, right. We're sort of in this weird situation, where C# has been a massive, main programming language in Windows, but at the same time, we are like complete newcomers to some other platforms. At least mostly so. And so it's this interesting situation, where now that it's actually becoming an option on all the platforms, we're at the same time very entrenched, and also very new and kind of the fledgling language on some of those platforms. We're eager to help that adoption on those other platforms. One other thing that is changing how and where you can use C# is the fact that we've evolved our language technology. So the compiler and IDE technologies that underlies the implementation of the language quite a bit, what we call Project Roslyn, and that's enabling some, I think, quite unique scenarios about how you can program in C#. I'm gonna show a little bit of that, because I think it's nerdy and cool, and maybe it's also useful to you. One of the consequences of that is that, that work on sort of the language core, and ripping it out of the, sort of, Windows and Visual Studios specifics, means that it's become very easy, as these things go, to implement C# and others IDEs. So you can essentially use C# in your favorite IDE, and we'll talk a little bit about that as well, or your favorite editor. And of course, one of the big changes is we've moved from being a completely proprietary technology, to being completely open source. So everyone can contribute to C#, and a lot of people do. And we're getting a conversation with the community that's vastly different now. It's more of a collaboration project, as opposed to, "Microsoft says..." And that's very exciting. It means that, rather than coming out every three years or whatever, and saying, "Ta-da, this is what we worked on, hope you like it." We are now in a very open dialogue everyday with the community about our direction. We get feedback all the time. Like probably, tens of you will come to me after, and say why we should be doing something different, or proposing things. And that happens online, and on GitHub, and elsewhere as well. So we have a much better, we have much better quality on our design work as a result of it, I think. Okay, so that's a couple of good things. Let's start with some of those other places that C# are. So how many people here have used Xamarin? So a few there. Have you all, you must all have used Xamarin on non Windows platforms, right? That's probably the reason why you do. So Xamarin, how many people are aware what Xamarin is? Okay, about half. Xamarin, it used to be a separate company. We acquired them six months ago. It's a technology for using C# to target, to make native apps for Android and iOS. So it's technology that's very much based on letting you use the same language, and the same source code, for the most part, to write apps for multiple different mobile platforms, right? So it works on iOS, it works on Android. It actually targets Mac as well, and by the way, Windows too, if you want to. And it creates high-quality native UIs. It's a number of big apps that are using this technology, because it saves the effort of separate implementations on those platforms. It also lets you use the language that you can use on the back end as well, which, yes you can with Java, but it's not quite there yet with Swift or Objective-C. And so, it's sort of economy of scale, and it's also just a very good language for implementing apps. It's based on the Mono project. How many people know about the Mono project? Okay, about half. That is an open source implementation done by people outside of Microsoft many years ago, and maintained ever since to target C# to other platforms and Windows. While we at Microsoft were sort of tunnel-vision on Windows for many, many years, these people saw the cross platform potential of C# much before we did and implemented this great cross platform. Cross platform implementation. So Xamarin is based on that, and a lot of the apps that you see in the iOS or Android are stores that are actually based on C#. Either because of Xamarin, or because of Unity, which is probably the industry leading game engine. So if you're up there on the back rows playing a game instead of listening, chances are, it's written in Unity. Right, so even your hands are engaged in C# right now. So again, this is based on Mono, and this 2D, 3D game engine is one that you essentially target with C#. So a lot of those games out there are written in C# as well. So we do actually have this cross platform reach in many of the client technologies that many people are not aware of. So I wanted to call that out. Also at Microsoft, we are working on what we call .NET Core, which is a fresh implementation, if you will, of the whole .NET stack, the runtime, and the libraries, that's intended to be lightweight, and for kinda server-side use; for Cloud, and server workloads. It's also cross-platform, works in Linux, Mac, oh and Windows. And we're putting the ASP.NET framework on top, which is very broadly used web framework, that you can now run on non Windows machines, and it's open source. So this kinda helps with, why are we building a separate one? Well this helps with, sort of the more, the lighter weight things that you wanna do when you're on the server-side. First of all, there's no UI framework, but it also is able to do stand-alone deployment. For instance, you can ship the runtime together with your code, so that you don't have dependencies on various things being installed on the box that it happens to run on; in the Cloud somewhere. So it kinda has a better architecture, makes it a lot more suitable for microservices and stuff like that. So it's kinda trying to modernize our platform for the server-side as well. How many people have dabbled with the .NET Core so far? So quite a few again. Wow. Given that the tooling isn't even at RTM yet, I'm quite impressed. Do you like it? Okay, I'm glad to hear because a lot of people don't yet, but I think we kinda just need to finish it properly. So this kind of proliferation of all these different .NETs that run on different platforms, or sets of platforms, creates a little bit of confusion, especially if you're a library provider. You wanna try to write something that runs on multiple different platforms. So we also do one called .NET Standard, which is, we're specifying, instead of APIs that are supposed to be an all-compliant .NET platform. So if you target that, and you could sort of just say target .NET Standard in your tool, then the thing you write will run everywhere. So you kinda claw back the ability to write code that works everywhere in the .NET ecosystem. And we'll evolve the Standard overtime, including new, kind of core essential libraries, and you can then target whichever Standard you want. So that's pretty much the rub on where C# runs. And hopefully that should convince, if there was anyone in the room who needed to be convinced that, people that there's a much bigger addressable space for C# than there's sort of traditionally been. And it's kind of exciting for us to be able to target that. So I wanna go to the more geekery side, and talk more about the Project Roslyn. So, I said that we modernized the C# language engine, if you will. It used to be that there was a C# compiler. It was written in C++, and then there was Visual Studio, and some language integration there for C#. Both kind of understood C# in their own way, just a little bit of code sharing, and nobody else could kinda get in on the deal. If somebody wanted to understand anything about C#, write a tool, or add their own IDE support or whatever, they were kinda lost. They had to start from scratch, because it was all black box. And that was kinda unsatisfactory for us as well. So when we decided it was time to rewrite the compiler, not only did we do it in C#, but we also took some strong architectural stands, if you will, on how it should be done. So essentially, I don't think we articulated it quite this way when we started, but this is kinda how it turned out; that there should really only need to be one place in the world, where the C# semantics are implemented. We should build the thing that everybody can use for everything they want to do with the language. Regardless of platform, regardless of what it is they're doing, regardless of whether it's a batch process, like a compilation, or whether it's an interactive situation like an IDE, full of erroneous code and all that stuff. It should work for all of those things. So it's pretty it's a pretty lofty goal, and it took us quite a while, and a lot of people worked on it. But we now have the Roslyn API, which really does satisfy this goal. And most things out there that understand C# are shifting over to Roslyn. Not all of them. The speaker in the room, Ted Brangs, is an exception to this for technical reasons of their own. But so the idea really is that this is the code base that you use to implement IDEs and editors. And if you have analysis tools of various kinds, linters that call out problems with your code. If you wanna manipulate code, like have automatic fixers, or refactorings or whatever, that produce new code from old code, you can use it. If you actually generate source, you can use it. If you're doing more interactive things, like scripting, or REPLs or whatever, like we have now a C# REPL in the Visual Studio, for instance, it's built on top of Roslyn. Oh and it still does compile the code as well and produce output. So, this is sort of a sampling of the kinds of things that you can do, and that people are doing in Spades with Roslyn right now. So it has really created this explosion, this can be an explosion of language based tools, because people can now get off the ground much faster. It sort of democratizes working with the language. You already have something you can ask about, the syntax and semantics, you just need to add the specific bits to what you wanna do. And one particular community project that makes really great use of this is OmniSharp. How many people have heard of or used OmniSharp? So that's too few. More of you should know about OmniSharp. It's really a project to make C# available on your favorite editor. Okay? And the way they do it is pretty clever. Because C# now runs everywhere, they can take the Roslyn C# engine, and they can run it in a separate process on whatever machine you're developing on, be it a Mac or whatever. They run that as a separate process and then they only need to do a thin integration into whatever integration layer that particular editor has that talks on the wire, using some wire format, talks to the process about everything regarding the language. So every time you press a key, like you press dot, and you wanna get completion, it asks the process next door, like, "Hey, they pressed dot. What should I show in the completion list?" And it knows all the semantics. It'll tell them, "Oh these five methods are available, show those." And it's kinda this separation of concerns, where all the language understanding is wrapped up in a separate process, and can be created over that standardized wire format. And so that made it possible to go and implement really good, semantically-aware C# modes in lots of editors that some of you might love it, or hate or whatever. Some of which are sampled up here. I should note that Microsoft's Visual Studio code, for instance, uses OmniSharp for its C# mode, which is an extension that you just load in like anything else. It's not built into the editor. C# is just an extension like other languages. So that's a pretty cool technology I think. I also want to. It's time for some code, I think, and I don't know if you're itching for code as well, or it makes you sleepy. It's probably 50-50. I should go out and see if I have my project still running here. So let's do, probably the weirdest, geekiest example here. We have some resolution issues here. Can you see the code on the back row? - [Audience Member] Yes. - [Instructor] Yes? You can actually read it? - [Audience Member] Yeah. - [Instructor] Cool. Well it is a pretty big screen up there. Good! So what I wanna do, is one of the things we did to kinda help people get started thinking about language-based tool, and tried to democratize is we created this framework, that we call the Analyzer framework, where it's really easy to build something that analyzes people's source code, and can give diagnostics on it. And also to build something, that when you get those diagnostics, it will offer up fixes to the code. And so if you think about your organization having special code styles that you want to enforce, or you have refactorings that you wanna build, because you often do this kind of manipulation of the code yourself, or you wanna share that with the world; you have fixes that you often find yourself doing that you might as well automate; this is the tool for you. And this is a project type that you can just install in Visual Studio and start using. When you open the project, it comes with a bunch of boilerplate already built for you. So what happens, specifically, when you enter debug mode on a project like this, is that it takes that analyzer that you were writing, and the code fixes and whatever, and it installs them. They can be run in batch code or whatever, you can ship them as a nougat package, but what I does is, it actually installs them as a Visual Studio extension, in a nested version of Visual Studio that it then runs as part of the debug mode here. So now I have Visual Studio running Visual Studio with a code fixes that I'm writing actually operative in the nested version of Visual Studio. So let's open some code in the nested version of Visual Studio here. And so I should say, I haven't completely written those analyzers yet. We'll do that together. So it doesn't do anything yet. But here's some sample code that we want to operate on. The thing I want to implement is fairly syntactical, just for simplicity, but I could have implemented some Antegros as well. The Roslyn engine provides complete information for me to use, but what I wanna just say here is, it's bad style to have statements inside of ifStatements, or else clauses, that don't have curlies around em'. We wanna implement that old-fashioned, rigid style of there always have to be curlies, because then you don't get so many bugs as you edit the code later. So we wanna actually complain about this code in those cases, and for the sake of time, I will only implement it for if, but we could also implement it for else. So let's implement a little code analyzer live here. So we go back to the running code. I'm not actually gonna stop the nested thing here. I'm going to just put a break point. So what I did is essentially, what I did ahead of time is I'm just registering that, whenever we see an ifStatement, we should call this method AnalyzeNode. That's all I did, and so whenever the source analysis in Visual Studio hits an ifStatement, go here, okay? And let's then go and trigger that. So if we go to the nested Visual Studio here, and I do an edit, it will reanalyze the code, and boom! It'll hit the break point and I now get all kinds of information about where I am in the code that I can start working on. So the thing that I get past is a context object. So let's look, what's inside of that: context. Hmm, it looks like I am able to report diagnostics if I don't like this ifStatement. I can also get the node of the syntax tree that I'm looking at, which is the ifStatement hopefully. So let's start getting that out and if we hover over it here, since we're in debug mode, that's an actual object that got passed in. We see that it is indeed an ifStatement. Sorry that the font is a little small here. So let's get it as an ifStatement using just, essentially Roslyn is an object model for code, right? So I'm just looking at a syntax tree node, and it happens to be of the derived class that is a ifStatement syntax here. So we can say var ifStatement is that thing. And now that's the only kinda thing we're gonna get called with, so I'm gonna skip checking that it actually was an ifStatement. And we'll just say, when is an ifStatement wrong? Well it's wrong if the ifStatement's statement, the thing that's inside of it, if that is not something with curlies around it. That's called a block. So if the kind of thing that this is is not a block, SyntaxKind.block, then I wanna complain. Okay? Then I wanna say to the user, "You're wrong." And so what I essentially want to do is take that, remember that report diagnostic that I have here. Now I'm gonna report a diagnostic. Okay? And what am I gonna put in there? I'm gonna put a diagnostic. Okay? Whatever that is, let's call it Diagostic. So I don't have that yet, so I'm going to use a little refactoring to generate a local for it. It turns out I can create a diagnostic by saying Diagnostic.Create, and it takes a few things I happen to have prepared. A descriptor, sorry, is called Rule, and then I need some kind of location. That is where to put a squiggle in the code when this problem appears, and then I need to say what kind of statement, what kind of thing I'm looking at here as well. So okay, and we need or find out what the location is. So let's do that refactoring again, generate a local. This is all while I'm in debug mode, by the way, I'm actually debugging right now. Let's see, what is the location? We're probably, the node that I'm looking at, the ifStatement. Where do we actually want the squiggle? Let's have it on the if keyword, alright? So the ifStatement, what does it have? It has an if keyword, because this is a concrete syntax tree. It has all the details about the code, including where everything is. And so let's get the location of that. Let's see there's a get location method. Let's get the location of that if keyword and put that in. Okay so I just wrote some code. Let's see if it actually works. Let's remove the break point, and keep running in the debugger. We wait a little to see what happens, and now you see squiggles appear in the ifStatements up here, right? So that was all I had to do: was write those three, four lines of code in order to identify the problem and tell the framework where to show it. Okay? And just to prove to you that it actually works, I can go, where did that sound come from? I can go and put curlies there and the squiggle will go away in that half. Alright? So essentially we've created a very easy to use, it gets a little harder when you start to do complex things, but a relatively easy to use model of the language, including its full syntax, and its full binding semantics, and so on, so that people can build tools, share them out, and the whole editing experience for everyone using C#, regardless of which editor they use, as long as it's based on Roslyn, and regardless of which platform they're on, they can benefit from these. And the analyzer that I wrote can be equally run in batch mode. It could be part of the compilation process and it could flag warnings or errors, just like the compiler does and its own native things. Alright? So let's see, for time, I'm probably gonna skip. I could also implement the fixer, but I'm not gonna do that in the interest of time. But we could also write a little fixer, it's not much harder, that actually fixes up the code, and puts those curlies in. Okay, so that's sorta the geek-out on the Roslyn side, and how that hopefully helps people get a better editing experience, a better development experience with C#, quite outside the language. It also gave us a much better code base, a much better architecture code base, and obviously one in C#, so we can dogfood our own language, that helps us evolve the language itself. It's a lot easier for us now to evolve the language, and for the community to participate in that evolution through contributions. So let's take a quick reminder of the evolution of C# here. That's a lot of versions. I'm not gonna go through all of them, but I think what it kinda shows is this kind of aggressiveness that we've had in innovation. I may wanna point out the Async. There's a couple things, where I think we kinda did fun things in the language. We did the link, the queries that we introduced in C# three. One of the things that we try to do is, we try to take concepts that exist in interesting languages that aren't very used, and we try to mainstream them, and kinda pull them into C# as a mainstream language, and help bring them to a broader market, if you will. This is definitely an example of that. The link queries in C# are an example of comprehensions that you find in functional languages and so on. We pulled those in along with Lambdas. Now every language in the world has Lambdas. It was a little less common back then. Java got them now I hear. So that's pretty cool. Of course, way back in C# two we did Generics, only a little later than Java did. I actually got to be part of introducing Generics to Java, then went to C#, and was part of rolling it out there. In C# we did it right, in that, I'm sorry, I'm getting into Java-bashing. I shouldn't really. We did it right, in that, Generics are kinda deeply implemented into the runtime. Java did the more cautious approach of making Generics something that the compiler compiles away. When you have it deeply in the runtime, that's really good for, first of all, getting the semantic 100%, but it also means that the performance characteristics are very different, especially when you have value types in the language, like C# had from version one on here, that Java's possibly getting it sometime in the future. When you have value types, you really want Generics to recognize those and kinda specialize for those value types so you don't get a lot of boxing and allocation around using Generics. It has to be that Generics makes your code faster, not slower. And Generics has really been the work horse for many of the language features we did since then. We were able to do queries right, because of Generics. Because the Generics was deeply implemented in the runtime, were available through reflection, as we did all kinds of weird code quoting, and translating C# to SQL, and all that kind of stuff. It was all based on the fact that the types would flow, and that would be available even at runtime. Dynamic we integrated dynamic-ness into a static type system, by having a type for when things were dynamic, called Dynamic. Again, uses Generics heavily under the hood to make that efficient, and to avoid a bunch of boxing and stuff. Async: very deeply reliant on Generics as well. Then in C# six, we got Roslyn, and we were like, okay now it's no longer a big war to implement any given language feature. We actually have more agility, and so now is the time to take all those little features that we never got to implement, that we wanted to implement, to just make development easier, and nicer, and lighter, and cleaner. And so we did a swath of those in C# six, which is the version of C# that's out there now. And then in C# seven, we're taking on some of the deeper features again, that we think that we, again, borrow heavily from the functional world, and we think that we are essentially taking the next step, in terms of dealing with data that's not necessarily so object-oriented, if you will. I think you're seeing us start as a very object-oriented language and kinda lean towards a more functional style as a supplement to the object-oriented, if you will, and trying to integrate those as well as we can. It's a bit of an inspiration from Scala, if you will. and what it's doing on the JVM, which is to try to make functional and object-oriented work well together, but definitely with our roots in the imperative object-oriented world for our situation. And so I think the next thing we should do, I'm gonna skip the Async demo, since most of you probably know what that is about. And then let's talk a little bit about what's coming into C# seven. So how many people actually use C# six? Or knew? So that's quite a lot of you. So many of you have a feeling for what's in there already. So with C# seven, and now I apologize to the few in the room that aren't C sharp-y, if this gets a little too deep here, but, I think, hopefully it's still useful to see. I didn't plan to kinda show all the new features that are there, but I think some of the most important ones are worth looking at. They kinda goes to some of the common situations you find you're in, where the sort of standard C-style object-oriented paradigm get a little in the way. So let's start out with tuples. Okay, so I have this is my whole program here. So I have some numbers. Actually, since they're, they're sort of recognizable here, but not everybody may know them by heart. We actually have binary literals now. It's kind of a tiny feature, but hey. It's good for when you're teaching your kids to program, right, oh these are the bits that are underneath these numbers. Okay, I'm gonna stop here. No actually, I'm gonna make one more, because another thing we also did, this is totally just in there. I'm just doing this because, yeah I don't know why I'm doing it. But we also have digit separators now so you can, like other languages do, so you can put underbars wherever you want, so the numbers get easier to read. And if you want many it's fine. So okay, now let's leave the 32 there. So what I wanna do is I wanna implement a method called Tally, that summarizes the numbers in an array, that sums them up, and also counts them. Okay? So we'll tally these numbers, okay? Of course I don't have that method yet, so let's use the refactoring to generate it. So this is static method here. It returns void. It probably should return something else. So here's the question, right? Should it return the sum or should it return the count? Both, yes right. Okay, so the idea is you can only return one thing in C# today, but tomorrow you can return two things, and three, like cuddling, but you can also return four. So if you were in the room last week cuddling, we beat you by one. Actually we beat you by infinite, because you can have as big tuples as you want, but it's probably a bad idea. So let's return two ints, okay? So this is a tuple type, and it sort of deliberately, well it's a tuple type. So it says two ints, so it should be pretty easy to understand. And here's a tuple literal that we'll return a dummy for now to get started. That then consists of some values, also with parentheses and commas, and that shouldn't be too surprising as syntax for it. And so when I go up here, I can take the result of the tally, and I can look at it, and lo and behold, it's a tuple. Great, so how can I use a tuple? Let's print something out, since this is a console app. That's pretty much what we can do. Interpolated strings, we love them. The sum is probably the first thing in there. So let's see, t. Let's see what a tuple has. It has an item one and it has an item two. Okay, it's kinda obvious what they are, so we can use them. Not the best names in the world, but it works. t.Item2, okay. So here's something that works, but it would be nice if they had nicer names. So tuples in C# can actually optionally have names for the different elements here. So now I give them names. And what does that mean? Well it means that when I get it back, it tells me what they are, a good, sort of, operational comment, if you will. It also means though, that if I go here, and press dot, in addition to these, which, this is a preview; the final version should probably hide the bad names. We have the good names, because you can see sum is here and I can use that name instead. So these are the, sort of, real names of the underlying type, but the compiler knows to keep track of these other names and show those instead. So you get a nice experience going against that. So I think it's important that tuples have names in them, because who can remember whether it was first name, last name, or last name, first name, and all those things, right? They need to come with that information, and it needs to be operational. You need to be able to get it. Of course, you might prefer to immediately pick the tuple apart as you get it and deconstruct it, and you can do that too in C#. So you can say sum, count here, and now the tuple immediately gets deconstructed into sum variable and to count variable that get declared here. And instead of t. here, we can just say sum and count. Okay. Alright? Tuple names, yea? (audience applause) So let's go now and implement this method for real. So instead of returning just a dummy here, let's return a result, and let's make the result equal to that dummy value here to start with. So what we wanna do is we wanna, foreach of the numbers, let's call them values, because I like that better. Let's foreach of the values, and var v in values. And then we want to update the result every time around. So we can say, actually result is too long. I wanna just call it r. Is that okay? There we go. So let's just say r equals, and then a new tuple literal, r. I wanna get the old value out. I wish the r had names as well. Let's go and give it names. You can give names in the tuple literal as well. So you do that with the same syntax that you use for named arguments. So now r has a "s" and a "c." So now we can say r.s, the sum that's already there, plus the new value, and the count that was already there, plus one. Okay? You might be justified in wondering, isn't this terribly wasteful? Isn't he allocating a new array? Or a new tuple every time around in this loop, and in these resource constrained devices, and cycles that cost money on the Cloud and so on? Isn't it wasteful to allocate all these tuples? And it's not because the tuples aren't actually objects. Tuples are implemented as a value type, as a struct in C#. So they're not allocated. This is just really in place, updating some stuff that's already on the stack. Right, so their value types are passed by copy, not by reference. Tuples don't have identity, they just have values. Okay? Which I think is the way tuples should be. They should sort of be ephemeral. They shouldn't have this kind of life of their own, and also it's more efficient, so that's good. Tuples are not only value types, they're also mutable. And I know there are people in the functional camp that are going to revolt about this, because they already have, but tuples are mutable. You can mutate a tuple. So instead of doing this, I could write, it's probably less elegant, but I could write, r.s += value. And as a separate statement: r.c ++, no pun intended. Well a little, but I can actually mutate the tuple in place, because that's not dangerous, because there's no shared mutable state among threads or whatever here, because it's a struct, right? Nobody's sharing it. You pass it to someone, it's a copy. So it's not actually dangerous. So we just said, what the heck? This is one of these, like, why does it always have to be so object-oriented, right? Why does everything have to be encapsulated? And so tuples don't have properties, they just have fields. They're just a struct with some mutable public fields. There, alright? It's as simple as it gets, so you understand what you have. I think that's right for tuples, because they're not really an abstraction. They're not wrapping something. They're just values. So let em' just be values. So I could do this, but let's actually not, because I like the other thing better. Okay? So the remaining few things there are to say about tuples is that, since it's a type, it has value equality. So you can use it as a key in a dictionary, for instance. So that means, if you want to be keyed off of two things, they both have to be right, then you can just the tuple as the key, and everything works right; the hatch code and everything work out right in the data structures. Also, of course, it's a good way to get multiple results back from an asynchronous method, because if your Async, and you return task of the tuple, then it all works out when you go up here and await it. The tuple comes back out, and you can deconstruct and keep going. So they're a good transport. For the situation around multiple results was even worse for Async methods and other methods, because you couldn't use out parameters, but now you can just use tuples. Okay? Of course I don't get to await, because that thing was not Async. But ignore that, okay? So that's tuples for you. The other thing that I think is quite interesting is that we are starting to add pattern matching to C#. And that's a whole new concept that we're bringing in from the functional camp, and we're sort of doing it gradually. So I think that you'll see more on that front in later versions of C#, but we're taking a big step, I think, in introducing the first couple of patterns. And so how does this work? Well let's turn this example into one where we have recursive lists of numbers. So instead of an int array, this is an object array, where we just have a convention that the things inside are either ints or they're other arrays with ints in them. So new object array, with some of these ints nested inside, like this. Maybe there's also a null in there for good measure, and now we wanna update the tally method, so that it can deal with that. So let's take object arrays instead here, and now we get an error here because v is not an int anymore. It's an object. So we need to know that it's an int before we can add it here. So we need some kind of logic there, and what we would do in the old days, is we'd do a type test. So well say if v is int, then we can go and do this, but of course, even though we just checked that it's int, we don't actually know it again down here. We have to check it again and cast it or whatever. So what we're doing instead now, is we're, so first approximation, you could think of it as, we're extending the is expression. So that you can now declare a variable here. When you ask if it's in, if it is, then take that int and put it into the new variable i. And then the variable i has the value of v, but typed as int. So now I can add it here, and I know I'm good. Okay? So it's sort of just an extended version of the is expression, if you will. But what's really going on is that the is expression is now being extended to allow patterns, which is a new concept in C#. Patterns, instead of just types. And patterns can be many different things. They can't be very many different things now. They can essentially just be constants, or type patterns like this. It could be, a constant could for instance be, you could say v is seven. That's actually also now allowed because that's a constant pattern. And then we are taking these patterns, we're integrating them into language features, such as the is expression. The other place where we're integrating it, just to stay with the example here, is we're integrating into the switch statement. So if I say, if I say switch, if could spell here, switch. I can now switch on anything. It used to be that switch could just switch on primitive types. It's sort of this dinosaur of a feature, but now it can switch on anything. I can switch an object: switch on v. And now in my switch statement, I can have cases that have not just constants in them, which are now just a special kind of pattern, but the cases can have any kind of pattern. So I can say case int i, except we need to do something to entail a sense here to completion before we ship this. And I have to remember the break, that's why I'm getting the squiggly there. And now, I've essentially used a pattern. So I extended the case clauses in the switch statement to be able to apply a pattern, and say when this pattern applies, do this particular case. Right? And so now I can sort of modernize the switch statement a bit. I can also say case object array, which is the other thing I'm expecting. Let's call that a, and I can actually also put conditions in my switch, in my case clauses here. So I can say I only want the object a when a is longer than zero, because, a.Length is greater than zero, because, otherwise there's no work to do. Right, and when that's the case, I can do var t = Tally, the nested array, and go add that to r as well; r equals r dot, you know how it goes, r.s + t.sum, r.c + t.c) right? And a break. So again spelling helps. So this is a generalization of existing features with patterns, and that's how far we got in C# so far with pattern matching. There are some things that, if I go back to the slides here, some things that we would like to do. There are more things we wanna do with patterns int the future. First of all, we wanna have smarter patterns. So you should be able to have recursive patterns. We actually, I didn't show, but we actually also let you specify in a given type that it can be deconstructed. So you can specify an point type, for instance, that it can be deconstructed, just like a deconstructed tuple into separate variables. When things are deconstructable, why don't we put that together with the pattern matching, and allow you to, if both check that always a point, and if it is, deconstruct it, and maybe apply patterns recursively here saying, if o is a point, and the first part of that point. The x is five, then put the second part into variable y, and do something with y. So you can kinda get smarter and smarter patterns. You can probably also write unreadable code with this, but I think in general, it's going to be useful to be able to dig little deeper in the pattern. The other thing is, maybe we should come up with new places to have patterns. The switch statement is kinda, it is kinda sixties, right? And so maybe there's an expression version of the switch statement. Maybe it's a match expression, like it's called in functional languages, that has a niftier syntax, it's expression based, the cases are expressions, and your code gets a little more terse like that. But that's the kind of thing that now we have the notion of patterns in there, we can both add new patterns, and add new places where they occur. So that's one thing that we're focused on for the next generation of C#, which we're already working on, because C# seven is pretty much done. We just haven't shipped it yet, and don't ask me when. The other thing we're thinking about is, one of the things I talked about, kinda moving with the state of the art. And one of the things that's becoming mainstream in newer lovely little languages, is the ability to distinguish in the type system, when things are supposed to be nullable and when they're not. This variable is supposed to sometimes be null, it's part of its domain, this one isn't, so why am I getting all reference exceptions all the time? The previous guy here, he talked about the same thing for cuddling. And Swift has that as well, and so on. So we've been like, can we do something for C# along these lines, even though we've had seven versions now, where nullability has been purely a runtime thing? And we think we can, and it's along familiar lines, maybe, where we already have that trailing question mark in C# for nullable value types, so if we allow you to apply that to a reference type, maybe that's how you say that something is nullable. And if you say that, then there are things we won't let you do. On the other hand, if you don't say that, and you're up into this new world somehow, then we will expect the thing in there to not be null. And we will help you maintain that, okay? So what that means is I can assign null into the n, but not into the s. And I can't assign n to s without any qualification either, because that might be null, right? So I'm just protecting the variable from the kinds of variables that it's not supposed to hold. On the other hand, though, when I want to use it to reference it, I can do s.Length without any qualification, because I know it's not null. I know it's probably not null, cause we probably can't give any absolute guarantees in a language like C#, but it's probably gonna find most of the places where you're not supposed to dot. So, other hand, n.Length is gonna warn you about it potentially being null, and you potentially getting that null reference exception, right? And so the way to get around that is, some of these new languages, they have specific new null-checking features, alright. They have like a new way that pattern matching, or whatever you can use to check for null. We don't wanna change how you check for null. There are already, like, seven ways of checking for null in C#. We're good, thanks. So what we wanna do instead is to track, have the compiler track when you checked that something was null, then use that knowledge. So if you have an ifStatement that sees that n is not, in fact, null in this case, then we will know that in the scope of that check. It is, in fact, not null, and we'll assume that it's fine that you dot into it. Okay, are there ways to get around this? Yeah, but you kinda have to work a little to get around it now. Instead of the other way around, where you have to work all the time to eliminate all your null reference exceptions. So there'll also be a Dammit operator, we call it, where you can actually walk up to a nullable thing and put a bang, a post a bang on it, and that means, the thing you are, but assuming in the type system that that was not null cause I know better than the compiler. So sometimes you just know, you tested something else and you knew somewhere, and you know in this case, this is never null, and if you're bold enough to stick with that, you get to insist and we will let you dot without a warning. Alright? So that's another thing that, we're already working on this feature, and we're hoping to get it in the next generation of C#. So hopefully that's gonna be useful. The interesting thing about a feature like this is it needs to not only go into the language, but we need to make sure that our frameworks, and so on, are adequately annotated, so that when you build on those, you get the right nullabilities propagated into your own code. Okay, so it is a bit of a challenging feature, but I think it's worth it. So I think we are at the end, where I say, remember to fill out evaluations. Do know that we're over time. Thank you very much. It's a pleasure. (audience applauds)
B1 中級 GOTO 2016--為什麼你應該再看看C#--Mads Torgersen。 (GOTO 2016 • Why You Should Take Another Look at C# • Mads Torgersen) 79 7 colin 發佈於 2021 年 01 月 14 日 更多分享 分享 收藏 回報 影片單字