We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Something C# 7: This Way Comes

00:00

Formale Metadaten

Titel
Something C# 7: This Way Comes
Untertitel
Themes and features for the next version of the C# language
Serientitel
Anzahl der Teile
133
Autor
Lizenz
CC-Namensnennung - keine kommerzielle Nutzung - Weitergabe unter gleichen Bedingungen 3.0 Unported:
Sie dürfen das Werk bzw. den Inhalt zu jedem legalen und nicht-kommerziellen Zweck nutzen, verändern und in unveränderter oder veränderter Form vervielfältigen, verbreiten und öffentlich zugänglich machen, sofern Sie den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen und das Werk bzw. diesen Inhalt auch in veränderter Form nur unter den Bedingungen dieser Lizenz weitergeben
Identifikatoren
Herausgeber
Erscheinungsjahr
Sprache

Inhaltliche Metadaten

Fachgebiet
Genre
Abstract
If you want to become an active participant in the evolution of C#, come and learn how. Now that C# 6 has been released, discussions are ramping up on what C# 7 will bring. There's a candidate list of features in the design notes . In this forward looking talk, I'll provide an overview of the potential features. I'll discuss some of the current thinking on how these features might surface in the language. After discussing the potential features, I'll discuss how you can get involved in the process. Roslyn (C# 6) was open source. Now the design discussions are open as well. You will be able to comment on the language design discussions. You can help determine the final syntax. And you can help with the prioritization of different features.
36
61
Vorschaubild
1:11:04
73
107
SoftwareentwicklerAutomatische HandlungsplanungWhiteboardGewicht <Ausgleichsrechnung>Repository <Informatik>TermOffene MengeFormale SpracheStandardabweichungVersionsverwaltungProdukt <Mathematik>Coxeter-GruppeFlächeninhaltInstantiierungJSONXMLUMLComputeranimation
SoftwareentwicklerVollständiger VerbandMailing-ListeEinsFormale SpracheDatensatzMultiplikationsoperatorZahlenbereichCoxeter-GruppeOpen SourceBitExogene VariableHecke-OperatorNummernsystemMustervergleichDifferenteArithmetischer AusdruckMustersprache
Generator <Informatik>Open SourcePunktwolkeSoftwareentwicklerProgrammierungMeta-TagVerschiebungsoperatorFunktion <Mathematik>MustervergleichTupelTypentheorieObjekt <Kategorie>ZählenRechenwerkZählenTypentheorieProgrammierparadigmaFormale SpracheAuflösung <Mathematik>Objekt <Kategorie>InformationsüberlastungProgrammfehlerBitFunktionalCompilerProgrammierungElement <Gruppentheorie>MultiplikationsoperatorAttributierte GrammatikMetaprogrammierungClientServerMusterspracheGenerator <Informatik>ProgrammiergerätOpen SourceDatenmodellArithmetisches MittelTablet PCNotebook-ComputerVarianzSpielkonsoleMobiles InternetExogene VariableF sharpC sharpZeiger <Informatik>ComputerspielZusammenhängender GraphCodePunktwolkeEinsBefehl <Informatik>TermAbzählenStreaming <Kommunikationstechnik>SummierbarkeitBildverstehenSchreiben <Datenverarbeitung>VerschiebungsoperatorVirtuelle MaschineTupelRFIDVariableTaskPhysikalisches SystemPunktCOMRückkopplungProdukt <Mathematik>Klasse <Mathematik>Formale SemantikZahlenbereichStellenringInformationsspeicherungImplementierungMultiplikationVorzeichen <Mathematik>Innerer PunktGeradeDatensatzProgrammierspracheSoundverarbeitungPuls <Technik>DatenfeldDateiformatFlächentheorieRechter WinkelGanze FunktionComputervirusZeichenketteCoxeter-GruppeLesen <Datenverarbeitung>Gerichteter GraphAusnahmebehandlungDifferenteComputeranimation
TupelSynchronisierungTaskZählenSoftwareentwicklerMustervergleichBefehl <Informatik>DickeMereologiePunktKonstruktor <Informatik>MusterspracheÄußere Algebra eines ModulsOffene MengeArithmetischer AusdruckSoftwaretestTypentheorieBitFormale SpracheKategorie <Mathematik>MustervergleichInstantiierungGenerizitätProgrammfehlerVariableQuaderOrdnung <Mathematik>Wort <Informatik>Objekt <Kategorie>ComputervirusBefehl <Informatik>ZählenArithmetisches MittelVersionsverwaltungTVD-VerfahrenCASE <Informatik>TaskDefaultGerichteter GraphParametersystemVorzeichen <Mathematik>DifferenteVektorpotenzialDivergente ReiheGrundsätze ordnungsmäßiger DatenverarbeitungGüte der AnpassungTermSoundverarbeitungSchlussregelRechter WinkelDatensatzMatchingGeradePRINCE2Automatische IndexierungPoisson-KlammerSummierbarkeitTupelRechenschieberDifferenzkernSchreiben <Datenverarbeitung>DigitaltechnikVarianzp-Block
Befehl <Informatik>DickeSoftwareentwicklerMustervergleichRegulärer Ausdruck <Textverarbeitung>ZeichenketteMusterspracheTypentheorieDifferenteBefehl <Informatik>Ordnung <Mathematik>MultiplikationCASE <Informatik>Rechter WinkelInnerer PunktPoisson-KlammerVariableGanze ZahlDickeKategorie <Mathematik>ZeichenketteCompilerFehlermeldungKontrollstrukturWort <Informatik>RechenschieberRauschenDatensatzCodeStrömungsrichtungMathematikMatchingVerzweigendes ProgrammArithmetischer AusdruckMustervergleichMereologieFormale SprachePunktKlasse <Mathematik>Objekt <Kategorie>GruppenoperationSchlüsselverwaltungZellularer AutomatSpannweite <Stochastik>ZahlenbereichBitZweiBitrateGüte der Anpassung
ZeichenketteDickeBenutzerfreundlichkeitRegulärer Ausdruck <Textverarbeitung>TupelMusterspracheSoftwareentwicklerOffene MengeAbgeschlossene MengeGleichheitszeichenTypentheorieVersionsverwaltungDatensatzObjekt <Kategorie>MustervergleichFormale SpracheProgrammierungBefehl <Informatik>Schar <Mathematik>MereologieOrdnung <Mathematik>Arithmetischer AusdruckCompilerKonstruktor <Informatik>FunktionalGrundsätze ordnungsmäßiger DatenverarbeitungAggregatzustandBildgebendes VerfahrenAbgeschlossene MengeAusnahmebehandlungGeradeHypermediaCodeDemoszene <Programmierung>BitNichtlinearer OperatorÄußere Algebra eines ModulsKlasse <Mathematik>MatchingJordan-NormalformHash-AlgorithmusParametersystemCAN-BusSystemaufrufWort <Informatik>CASE <Informatik>Prozess <Informatik>Kategorie <Mathematik>ZweiResultanteZustandsmaschineOffene MengeRechenschieberMultiplikationsoperatorVollständiger VerbandMAPDifferenzkernRechter WinkelLoopt-TestMusterspracheENUMEins
SoftwareentwicklerZeichenketteVererbungshierarchieDatensatzCILObjekt <Kategorie>Typentheoriet-TestEinsRechter WinkelVersionsverwaltungKonstruktor <Informatik>Wort <Informatik>Kategorie <Mathematik>MathematikParametersystemQuantenzustandProzess <Informatik>ZweiTypentheorieMehrrechnersystemObjekt <Kategorie>BenutzerfreundlichkeitComputerspielMultiplikationsoperatorExpertensystemInterface <Schaltung>DatensatzHochdruckBitRückkopplungÄußere Algebra eines ModulsSelbstrepräsentationFormation <Mathematik>CASE <Informatik>DifferenteIntelZählenKugelkappeOrdnung <Mathematik>Klasse <Mathematik>Befehl <Informatik>CodeRechenschieber
TypentheorieSoftwareentwicklerVersionsverwaltungZeichenketteFunktion <Mathematik>DigitalfilterOpen SourceElement <Gruppentheorie>Klasse <Mathematik>ZeichenketteTermZeiger <Informatik>Elektronische PublikationProtokoll <Datenverarbeitungssystem>RechenwerkTypentheorieCompilerGeradeAnalysisTaskHydrostatikMusterspracheSampler <Musikinstrument>SystemaufrufKategorie <Mathematik>Perfekte GruppeVersionsverwaltungFehlermeldungFunktionalRückkopplungMustervergleichHalbleiterspeicherRechter WinkelDifferentet-TestSoftwaretestCASE <Informatik>Expandierender GraphDynamisches SystemFormale SpracheAnwendungsdienstanbieterSpiegelung <Mathematik>AusnahmebehandlungDatensatzParametersystemPhysikalisches SystemDickeMAPCodeAbzählenStellenringArithmetisches MittelMultiplikationsoperatorSchnittmengeNumerisches VerfahrenNichtlinearer OperatorGerichteter GraphOffice-PaketÄhnlichkeitsgeometrieVerschlingungSoundverarbeitungGraphfärbung
Funktion <Mathematik>DigitalfilterOpen SourceElement <Gruppentheorie>SoftwareentwicklerExplosion <Stochastik>IndexberechnungMultitaskingVisuelles SystemVersionsverwaltungFunktionalVisualisierungVersionsverwaltungKonstruktor <Informatik>Ordnung <Mathematik>Klasse <Mathematik>GruppenoperationFormale SpracheStandardabweichungLineare AlgebraDatenstrukturInformationsspeicherungProgram SlicingQuantenzustandMomentenproblemVektorraumCompilerHydrostatikBitrateDatensatzMatrizenrechnungAutomatische HandlungsplanungBetragsflächeHalbleiterspeicherAnalysisSoftwaretestRechter WinkelNumerisches VerfahrenDickeAlgebraisch abgeschlossener KörperInnerer PunktOpen SourceSampler <Musikinstrument>Interrupt <Informatik>BeobachtungsstudieMereologieObjekt <Kategorie>TaskTypentheorieSpieltheorieMultiplikationsoperatorSchlüsselverwaltungProgrammiergerätWort <Informatik>ComputervirusRohdatenMusterspracheE-MailQuaderSoftwareComputerspielOvalPatch <Software>p-BlockParametersystemAbzählenVarianzEin-AusgabeC sharpIterationMathematik
SoftwareentwicklerVisuelles SystemOffene MengeVersionsverwaltungExogene VariableInformationDokumentenserverSoftwareMultiplikationsoperatorBetragsflächeGebäude <Mathematik>Verzweigendes ProgrammTypentheorieHyperbelverfahrenOpen SourceDatensatzHinterlegungsverfahren <Kryptologie>MusterspracheTropfenDokumentenserverMustervergleich
Transkript: Englisch(automatisch erzeugt)
So, welcome, and I'm going to be talking about features that are proposed and planned for C Sharp 7. So Bill Wagner, I'm a C Sharp MVP, I work on the .NET C Sharp ECMA standardization
committee with John Skeat, I'm in the .NET Foundation Advisory Board. Note that I'm not on the C Sharp team. So there's an important thing about that as I go through this talk. When I refer to the team, I mean the people at Microsoft that are actively working on the product. But I'm going to use the term we a lot through this presentation.
Because something that's very new with C Sharp 7 is it's being designed in the open. You know that C Sharp has been open sourced, it's available on GitHub on the Roslyn repo. All of the feature requests, design discussions, and everything related to this next version of the C Sharp language is tagged as issues or design notes on GitHub.
We, all of us, can contribute there and bring in our ideas. So, for instance, on a few things there. If you look for any of the issues that have the labels of area-language design and design notes,
these are, why did that not switch to that screen? Hang on, let's get back over here. There we are. All right. So if you look at language design, design notes, any of those issues are the minutes of the team design meetings.
So you can read what the team is thinking about different features as they're going on. And you can comment on those design notes. In particular, one of the ones that came out early in April is the work list of features.
There are 178 comments on this particular language design note meeting. As we go through, we can see some of the things that are very strong interests, talking about tuples, talking about pattern matching, records, nullability, and so on.
Some of the ones that have some interest, people were pretty excited about them, thought we could do them, maybe not, hard to see. Some small but useful ideas. Interesting ideas, but that require CLR support, so maybe won't get done unless the CLR team goes and adds some of those in.
Probably not this time. Then we have probably never. One of the ones I like there, which shows a little bit of the sense of humor of the team, is if you look under the probably never, you will see XML literals. That is an issue that was made written as a proposal, so add XML literals and embedded expressions.
As you go on down, you can see that Neil Gafter assigned a few different labels to this, one of which was over our dead bodies. If you look, he also scheduled it for a future release, adding it to the when heck freezes over, that milestone, which has since been closed.
If you notice, he did that on April 1st. They did actually have a serious discussion over why that's not going to happen. But with any of the different feature requests that come in, people are commenting on the language features. Do I like it? Do I not like it? Will the syntax work? Will the syntax introduce new ambiguities?
And so on. A number of the proposals have come from the community. Sometimes the community even responds and says, no, this is a bad idea, here's why, before the team can respond. So as I go through this presentation, when I talk about we, I do mean we.
Any of us can do all of that. So there are a number of themes as they start to round out about what is going to matter in this next release. Cloud and devices. Okay, we kind of know that any time Satya speaks about the products in general or Microsoft's vision.
Cloud and devices. Working with data. And this is an interesting one because of the history of C Sharp. John went through this very well in his last talk. Boldly but gently embrace this shift from object oriented toward data oriented programming. If you think of when C Sharp first came out, the idea behind object oriented programming is I have the data
and I have all the methods that would manipulate or work with that particular piece of data packaged together as an object. That works great when we're writing programs that run on one machine. Whether it's a desktop machine, a server, or what have you.
If you think of the programs that we're writing now and they operate on multiple machines. Whether that's queuing different tasks to run on different machines in a server room. Sending data from servers to client machines, be they mobile or tablets or laptops or what have you. Now we're entering a much more data oriented programming model.
When we send data packets from our server to a mobile device or responses back from a mobile device back up to a server, we're sending just the data, typically in JSON format, at least today. But we're not sending methods and objects.
That changes the kind of programming paradigm we have. So how does a language like C Sharp, which started life as an object oriented or component oriented language, start to embrace the ideas of what would be a data oriented programming language? Where we now totally separate the idea of where methods are stored with the data they act on.
So that's one of the big shifts. One of the ones that gets to be a rather big bit in terms of the language but is a smaller feature that way is async streams. So now what happens when we can await reading something from stream? Reliability.
John just spent an entire hour on immutability. Some of the features that we're going to add in C Sharp 7 will make that easier. John made a great point that we often don't really write immutable C Sharp because the syntax makes it harder. It's easier and I type less if I create mutable objects.
So let's just do the simple thing, create immutable object and trust that people don't do the wrong thing. Well, what we'd like to do is continue to make C Sharp a pit of success kind of language. We'd like to make it so when you write C Sharp, the natural and easiest thing should be the right thing.
That's what we're trying to do with this idea of reliability. Nullability, I'm going to walk through some of the syntax there. Right now we have this idea where in value types I can create value types which can never be null or by adding the question mark character, I can create value types which can be null.
In reference types, they can always be null. How many people here have written a program that has ever thrown a null reference exception? Okay, I want to make sure everyone in here is a programmer. I see all the hands. What if we could, as of C Sharp 7, introduce the idea of a non-nullable reference type
and do it in a way that doesn't mean all your code is broken? So there's some very interesting syntax around trying to do that and trying to add that feature into your programs in such a way that it's backward compatible.
Small but useful things which are some syntax elements that we can do that are not that big but really useful in small ways. Private protected is one which is a super simple feature to implement. It got really bogged down in a really huge debate over how it should actually be surfaced in syntax
and we're going to try to bring that back. The idea of local functions, so I can create a function within a function because that's the only scope it should be called in. And a bit of history, C Sharp 6, the compiler team and working through Roslyn
completely redid overload resolution. The colloquial name for that feature was Better Betterness as we're trying to figure out which method of two overloads is better. Turns out there is a bug or two in Better Betterness. So it's time to do Bestest Betterness and remove that to really get rid of a couple things there.
Bestest Betterness, you won't actually see anything. I don't have anything discussing that because the idea is it would just actually work. We won't have those bugs. Metaprogramming source generators. The idea behind there is what if I can create attributes on elements in my program
and that actually injects a whole lot of code through the compiler. That could be really cool or could be really weird. Some ideas for performance, avoiding copying, improving interop with native scenarios or com.
Let's move on. So let's move on and talk about working with data. There are four or five different things that we can do. And as we work through this, I'm really interested in comments and feedback that we're going to take back to the team because they are discussing exactly how these features should be surfaced.
We have tuples, we have pattern matching, if anyone's familiar with F Sharp or other languages that have that. Concise data modeling to do records or unions. Initializing immutable types. John started to present a little bit of that as it got to the end of his presentation. And strong types for wired data.
How many people here have created DTO type classes for your C Sharp programs? How many people like that? You took a while to put your hand down. We're going to have a talk. So strong types for wired data, so we don't have to do that kind of really drudgery work.
So let's talk about tuples. So first the idea of a tuple, which we already have as a class, system.tuple, is what if I have methods that return more than one thing? The problem with the tuple class is its member names. First, second, third, that really doesn't carry a lot of semantic meaning.
So how can I create a method whereby the return type represents more than one item? Well, you create a class, you do all this typing and you have a name and you have all these things. Well, instead of that, let's simply say, well, let's just put our return type inside parentheses.
You can have as many as you want and we can give it names. And then my return statement would simply just return as many items as I need of the proper type. Great. So this method, Tally, returns an enumerable.
We should have the sum and the count. I can call it and get back this anonymous type. I can only use var for T, which is the tuple that is returned from Tally. I can deconstruct it, console.WriteLine, you can see T.Sum, T.Count.
So far so good. I could also deconstruct it on return. I could return, assign it to two different variables. You like that? This is good. Okay. Var S, Var C. Yes. So this is good.
I am glad. And then those two variables, we can put console.WriteLine, just S and C. Awesome. So far there's not a lot of controversy on this one. Most people have that reaction, actually. How about naming of fields?
In which part, naming them here? Okay, so in, we'll get to pattern matching in a bit. If I declare the tuple this way in the return type inside the parentheses,
I'm giving the names to the properties that will be returned from T. Okay, so if I use the variation where I have var T equals Tally of my values, the properties of T will be sum and count, which is what they are declared on the method.
Does that make sense? Does that answer your question? Whereas if I do the var, the deconstructed version, I can put whatever names I want. It doesn't have to match what's inside there. Yes. All right.
I can use tuples with async. So I can create an async task as my generic type parameter. Notice that my generic type parameter is a tuple, sum and count. Have the awaits inside there and so on, I'll return c.s.
Use it the same way we'd use async with any other return type. I can deconstruct it by awaiting the tuple itself or awaiting a deconstructed tuple, giving it my own variable names. Okay, so it should work.
The idea behind this is it should work with any feature that we have in the language today. So let's look at pattern matching. This is going to start to bend the language a little bit more. So here what I want to do, what I'd write today is I'd write if O is point,
open curly brace, point P equals O as point, and then I can do my write line. So we're just going to say if O is a point, assign it to the variable P. Inside my if statement, I will now write line P.X, P.Y.
Just saving some typing right there. Okay? So far that makes sense. Well, let's start to do a little bit more interesting pattern matching. I want to look for points that have the X value of 5. So now if O is point P and P.X equals 5, now I'm going to write the value of Y.
This will short circuit the same way our current if statement does. So if P is not a point, we're not going to try to, or if O is not a point, we won't try to figure out or assign something to X.
I could deconstruct it. I almost don't like this. I'd almost rather give them different names, but if O is a point, I'm going to say that the property X of the point I'm going to assign to the variable lowercase X. The property Y of the point I'm going to assign to the lowercase variable Y.
After I've done that, I'm also going to compare to see if X is equal to 5, and then I'll do the right line. The reason for this is if elsewhere in this we wanted to mutate, we can get a copy of it.
No. Go ahead. You get one. Yes. Yes.
It's an initialization. Yes. I find this one a little... Yes. We'll get to that. I'll get to that one.
I think you'll see why we want to switch it a little bit as I get to the next slide. If not, let's come back to that.
Yes. Two slides, I think we'll get to where this could get really, really useful. Who said this was a great idea? Who said this was a great idea? Mostly F Sharp people. I mean, no.
There is a lot of reasons. I think in two slides you'll see why it starts to really, really become useful. If I'm doing just a simple test like this, okay, I want to get the syntax down right now. A simple test like this, the syntax we have is probably sufficient. One more. I could use the construction syntax.
Let's say I only want to deconstruct part of it. I want to match actually not just on the type but on the values and do it in one place. Now, if O is a point whose variable or whose X property is 5, assign Y to its Y property and then just write that down.
So now we're starting to get to do something a little bit more interesting. I've got really compressed what I'm looking for, both the type of the object, the values of one of its properties, into a single expression.
Yes? Go back. Looking at a possible alternative syntax in terms of initialization versus the construction syntax.
It should work for anything that has a constructor if I remember the way the spec's written. Because it knows what point it is.
It's a good question. I'll have to think about that one. I knew you were going to have one. There was a question here and then over there.
If it's based on the constructor. If it's based on the constructor, good point. I think it is only for record types. Yeah. Yes. It's going to call equals on the property, yes. So it's going to use whatever equals means for that type in this instance value-based equality.
Yes. And we'll get to what we can do about that. Okay. Now let's look at switch statements and see, let's actually look at patterns. Where this really becomes useful is not I'm just doing one or two tests.
But I have a lot of different potential cases that I want to match against and take different steps. First thing I want to do is realize that while the syntax may look very, very familiar, this is not the switch statement you are looking for. So there's a few things that I want to talk about in terms of just how this is different.
One of the rules in a C sharp switch statement right now, as used in the traditional switch statement, is that you can rearrange all of the case labels and their corresponding blocks in any order you want without semantically changing the program.
Yes, you can. And I think that's a spec bug. Even the default case, I think that's a spec bug. Yes, okay. If you put brackets around it, the variable and scope case work. Yes, okay. So with pattern matching, John's getting all spec heavy here.
But in general, yeah, if I put brackets around variable initialization, it would work. Otherwise, it doesn't. But with pattern matching, these will be evaluated in order, okay? That's a few different things where there's some of the syntax, this is really under discussion right now,
where how do we want to expose this because it is different. One of them is if you notice, instead of what we would think of as default, we have star. Star must be last in this kind of a pattern matching switch statement. Notice that we have switch on O and we have all kinds of different types here.
If O is an integer, I'm going to write that it's a number. If O is a point, a record type with X and Y, I'm going to write both of those properties. If O is a string and the string is greater in length than zero, well, we'll write that string out. If it's null, we'll write the text word null.
Okay, so we're doing true pattern matching here, we're checking different types. We're also checking expressions onto what are the values of certain properties when a certain type is true. And notice those properties could be simple things such as the values of X and Y or a property that's returned from an object, the length, okay?
Yes, I think this is still under discussion.
So let's think about how we might want to be able to simplify some of this.
What if we didn't put break in place? Great? So here's an interesting realization from that, which is one of the things that's under discussion right now. Remember I said that in a current C sharp switch statement, the order of any of the branches is,
we can rearrange those without any changes. What that also means is the break statement in a traditional switch statement isn't really necessary. Because in C sharp, it's an error to fall through to the next case label.
It must end in a break, a return, or a go-to. What that means is you don't have to type the break, and if we said, okay, if you didn't type a break, that's what you meant, we could not have that error. That syntax was put into C sharp one because every other language that had a switch had a break.
So we wanted people to read it that way. Now if we look at something like this, and we say, wow, I like that? What would you think if break was optional in the traditional C sharp switch statement? Brilliant? Yes.
Then it's not a case statement. It's a statement with multiple labels. So far, people have been mixed on this. There is an open debate on this right now.
So go ahead and weigh in on GitHub. That is one of the important things that people are doing. Well, okay, let me get here. Yes. You're one slide ahead of me. Yes. How could anybody think of it? Because it's traditional. Well, that's why it's a compiler error if you don't put break there now, right?
So it is just noise. But this is one of the things that is very important as we look at how we want to do any of these features. It is noise that there is part of the community that feels certain things make code more understandable when they read it.
And that is an important consideration. I happen to agree with you. I think the break is just noise. Okay. Right. In this case, that is my thing. So I will let them know the consensus is no breaks anywhere.
This is good. This is good. Okay. Notice on the case labels themselves, pretty much the same thing that we saw before. Now let's go a little bit further. Can I go to the next slide, John?
Okay. So let's go to the next one. Suppose, let's make a pattern matching an expression. Right now, in any switch statement, that's because it's an expression, not a statement. Yes.
Match was discussed. And the idea was, well, switch is one thing people know. And the introduction of a new keyword that might not be contextual is very scary. Because if we introduce a new keyword into the language, but parsing, we can figure that out.
And parsing, no one anywhere has a variable named switch. About the which? That's definitely one of the reasons why match was proposed.
But a concern of adding a new keyword is there could be variables or classes or whatever out there using that text. So that's a very big concern.
And I think match was used there. It was switch and then match, I think, was one of the keywords that was looked at. So yeah, and that syntax is under discussion.
Is it the star? Nope, nope, it has to do with where it plays in. And if you notice the switch, the traditional switch is going to have switch and it's going to have the expression that is what you're switching on. And here it's switch and then the case labels.
Right? So that's how it figures it out, is if after the switch is the curly brace, it's the new style's pattern matching. If it's switch, expression, then it's the old style. Yes.
Can what? Yes.
Yes, you can, but you would have to arrange them in the proper order. So the question is, can I have multiple cases here for a point with different values and different things? You would have to put them in the proper order so that the way they would be evaluated, the order that they appear in text is the order they will be evaluated. Right.
Right, right. No, the first one that matches the...
Right. So you would have to put them in the opposite order. Put case int, five, case int. And then the first one would evaluate if it's an integer and it's five. And the second one would be evaluated if it was an integer that was not five because it already checked the first one.
Semantically, it is similar to what we would do with catch expressions for exceptions. They're evaluated in order, first one wins. So in this, the first one would win.
That's worth looking at. I will take that back to the team.
That's interesting. You want something that says only one of these is going to work. That was discussed. Right. And see, now we're back to adding break.
Yes. I think you're correct. I think I'd actually want to see it typed out.
But I believe that is correct. Right. If I understood what you were saying, that I'd have a switch, execute a case, loop back up and go through again? No. Okay.
Yes. Nope. Nope. Nope. No. No. Oh, is it a suggestion or a question? No. I think one of the key designs that they want to do with pattern matching is pattern matching will evaluate exactly one of these.
There is no way that it would be true.
Right. And that's one of the big reasons to do this. Right. I almost got to the next slide, Jai. Okay. So you can see we're...
Right. Mm-hmm. So the... I'm sorry? That's actually not a bad idea. Oh, yeah. If it could be contextual, that might work. Case given. That's an interesting thought.
Okay. Quick side note. The actual language design committee meetings are usually limited to a group of about six to ten people. And they're held in a conference room that won't seat more than six to ten people, and they don't do a conference call. This is why.
But very seriously, they do really try to discuss as many things as possible, and putting it on GitHub is a chance to do this. This is a very active discussion. So now we get to a very interesting question on this. If we do pattern matching expressions... There should be one in it.
So suppose we have tuples and patterns. So this represents a simple state machine for a door. If I wanted to open it or close it, and if I wanted to lock it. So I take its current state, which is open, closed, or locked, and a request for what I want it to do. Right? If it's closed, I want to open it.
Great. We'll return open. If it's closed and I want to lock it, fine. I can lock it. If it's open, I can close it. If it's locked, I can unlock it. However, if it's something else, like if it's an open door and I want to lock it, that's invalid. Or if it's locked and I want to lock it, that's invalid.
So I'll throw an invalid operation exception as that last match. Now notice something interesting. If that is done as an expression, what's wrong with that code that would not compile the way things are set up today? I want to see if somebody other than John knows, because I knew he would know.
Type might. There's no name on the enum. Yeah? You're returning a result out of a switch statement? Well, if I, from the last slide, if I said this kind of a record match, pattern matching is an expression, that returns a result.
Anybody else have an idea before I let John? Throw is a statement, not an expression. So what that means is throw needs to become possible as an expression.
We need to have a throw expression rather than a throw statement. Because what do I return? A throw. So that now introduces some new interesting things.
Note that the alternative would mean this would have to go back to having the curly braces, a return statement for open, closed, blah, blah, blah, and a throw statement with all the semicolons and the extra ceremony. That's why this one's really being considered. Okay.
Now we'll get to record types. Record types also really hopefully help us with immutability. So the idea here is let's define, this started to come up in C sharp 6 with the idea of primary constructors. Part of why primary constructors were pulled is because record types are a whole lot more useful.
And a couple of the things for primary constructors look like, well, maybe we haven't thought about this enough yet. So let's look at this. This is a record type for a person with a first name and a last name. First and last. That would generate all this code and just a little bit more. Right?
So I have a public property for first and last. Note that they only have the get keyword. So they are read only. Unimplemented properties. Generates the constructor with first and last. This dot first, this dot last. We will annoy John Skeet by violating the convention that the constructor parameters are capitalized rather than camel case.
It will implement equals. It will implement both versions of equals. The version for person, version for equality with an object.
It will implement I equatable of person. It will override get hash code with a great hash function that will be generated by the compiler. And something you may not have seen before. It will also implement this deconstruct function which turns it into a tuple. Because that's a nice thing to do with records.
Okay? Again, trying to be really, really productive with this idea of a record type. So person generates all that stuff. Programming with data. This would be the canonical form of an immutable person. And the compiler will generate all of it with just that one line.
Anders gets applause here. I'm just going to say, you know. Okay. I believe the proposal is going to be very, very consistent with F sharp's record types. There are some things that will likely be interesting and different.
Because of some of the things we have to do with here. So let's say I have a person. We know what that means. We saw the code that that would generate. Let's say for my particular problem, we're also working with a class of a student. Which would be a person who also has a property of a GPA.
Now let's look at three possible syntax ways to express that. And let's discuss both the pros and cons of each of them. And then I really want to get feedback from everyone here as to what you think makes more sense. Okay. Let's look at the first one. First one says, all right, I'm going to add the extra property for a record that is a student.
I will explicitly call the base record constructor with the first and last properties. And there we have it. Okay. Who likes that syntax? Okay. For the people that like that syntax, what happens if I name first something different for the student?
Maybe it's first name. Should that compile or not? Yeah? If it compiles, does that introduce a property of first name that is a member of student? And a property of first that is a member of person?
And does it hide it? Or does it merely change the name of the constructor parameter? This gets to be? It's illegal to rename it. Okay. That is one proposal.
That is one proposal that is out there. The other one is what can you do? Yes. Yes.
Okay. I have to use name parameters. I have an even better solution that I think comes in the next slide. Either that or two slides.
We'll get there. I want to finish this discussion, but we'll get there. Okay. Now, second one is if I'm merely extending this record type by adding new properties, how about student just says GPA and I declare that I'm deriving from the record type person and I don't specify any of the other parameters?
Advantages to this? It forces that you would create a student by calling the parameters, providing the arguments in a certain order, first, last, GPA. You can't rename them because you don't get two. And you avoid those problems.
Disadvantage? It's kind of hard to read. Because if I look at this, either in IntelliSense or F12 into the definition, I don't even see the other two parameters. And then there's a related problem. If I use that second syntax, how big are the changes to the XML commenting engine to parse that?
Because now we have these other parameters that aren't even there. They get picked up from something else if you're using XML comments for documentation and so on.
So who likes this syntax? Okay. Then how about the third one where we just move where the parentheses are over to the right of the base class? Anybody like that one? I thought I saw it. Okay. It has some of the same problems.
It's just an alternative representation. Let's try this now after looking at all this. Who likes the first syntax the best? Okay. You don't have to, John. You'll get your chances, I'm sure. Okay. Who likes the second syntax? Who wants to propose their own?
Has a better idea. Go ahead and write it up. Don't allow subtypes on record types? Mm-hmm.
That might need CLR support. Because I think, okay, that's an interesting thought. All record types should be CL classes. Yeah.
That would be, I don't think there's a proposal on that, but that would be one way to solve that problem.
Yeah. There's a reason why it might be useful that I'll get to. You may not agree with it, but there's a reason it might be useful. Yes. Yeah. I'll get to a little bit where it might be useful and has to do with wire types.
Okay. All right. So now let's look at creating immutable objects. This gets to your question on, hey, if I've got these things, this record type, and I've got all these booleans, I want to name them. This should be supported. Why can't I create an immutable type using the exact same syntax I would use to set the properties on a mutable type with an object initializer?
That should work. Okay. Great. So we got that. The next thing we want to do, because working with and creating copies of immutable types is rather annoying if you were in John's last session.
I have to create this copy. I have to do a new property. I have to do this. So let's have this with keyword that says I want to create P2, which is essentially a copy of P1. However, I am going to negate the value of X. Notice that this is using the object initializer syntax, so I can put as many of the properties as
I want to change in one with statement rather than our current version if you've worked with the Roslyn APIs of doing take this dot with something else, dot with something else, and so on and so forth. Very concise syntax, and yes, John, it will do that without doing a dozen copies.
It will do just one, replacing all of the appropriate properties. Code generated for that would be a constructor, creates a new immutable object, copies the ones you want copied, and replaces the other values that you want.
Now, strong types for Royer data. Let's start with just this right here. What would you think this does? And there are two reasonable answers, which is why there's a lot of discussion on this right now.
Okay? That is one of the correct conceptual ideas. Read the next JSON object, populate an anonymous type that implements the I person interface, set the properties on I person, let's assume first and last name, and return that object.
Okay? That's one of two proposals. It works really great unless you end up with something like this. What if the thing that came across the wire is of some type that is derived from person, a record type, by having more properties, which is actually a very common problem in JSON, right?
We're going to read some JSON data, see what's in it, some of the properties might be optional. We know it's something that looks sort of like this but may have other properties. If I only pull off the wire or convert just those properties from I person, I've effectively sliced it and lost those other properties.
Which can be good if I don't want to pay that memory cost, but it's bad if I want to see if that actually is something, data that I need. So now we have this idea of how we're using pattern matching then and say if P is a student S,
well now then I want to pull that extra property off the wire format and populate yet another property that I can get. That's the second possible answer of what this means. Okay? This one is a lively discussion.
Okay? When you pull stuff off the wire, do you immediately know how you want to work with it? Or do you have to do some testing first to see what it really is and then figure out what type it could be? Where pattern matching might come in handy.
Thoughts? What is the more common case here? This gets back to the idea should record types ever support inheritance at all? And if they do, how should something like this be interpreted? That probably would not be supported.
Because we do want to say what do we want to pull off the wire? If you did VAR it would be effectively what you're doing right now with say Newtonsoft or some other JSON. Right. This is meant to work something like what was called lightweight dynamic for C sharp six and was dropped. It's meant to kind of expand on that and see how should that work.
That is one design that would work perfectly. Why do we need inheritance at all? And that gets to the idea that record types should be sealed. I'll just define two different types and then never support inheritance.
And that is in fact one of the big discussions. Anders really likes solving this problem. If you've written anything in TypeScript this is really powerful stuff if I can get it to work correctly.
So I'm going to move on because there's a few I really want to get to that I know is coming. All right. Reliability. Here's the first big really interesting problem that I'm curious to get some feedback. See if you even believe this is possible. So I want to add the idea of nullable and non-nullable reference types.
So I should be able to specify that any reference type any place it's used is going to be non-nullable. No more null reference exception. And the challenge is can I add to the type system a non-nullable reference type at version greater than one without just making people scream.
Turns out there's a proposal that says maybe you can. So suppose I introduce this idea of string question mark which is a nullable reference type. And string would be a non-nullable reference type. So the variable s would always have to have a non-null value. You would be able to turn this feature on at the compilation unit level.
So your existing code base compiles like it does now. And you can turn it on on a class by class or compilation unit by compilation unit as you clean up code.
It would typically be a file. But the spec doesn't say file. It would be as you couldn't. In layman's terms it's a file. You can put it in at the top of a file. Yep. Okay. So if I try to set n equal to null.
Okay. Fine. You said that was a nullable string. No worries. If I try to set s equal to null, you're going to get a compiler warning. Because you've said s is a non-nullable string. So once you've turned this feature on, that's a warning. If I set s equal to n, well, from what we can tell here, that would be a warning.
Because n is a nullable reference type and s is not. If I do write line s dot length, I'm dereferencing a non-nullable type. Okay. That should work just fine. If I dereference a nullable type, I will get a warning.
Because that could be null. To make this feature actually useful, if from a static analysis standpoint the compiler can tell that n dot length or n should never be null because you checked, you will not get a warning. If the compiler can determine that that's true.
And that will flow through function calls and so on. If you declare an argument, has to be a non-nullable string, okay, anywhere in that method, that should be fine. Yes. I'm sorry? Why a warning and not an error?
Probably because there's just enough of a concern that the static analysis won't be perfect. Backwards compatibility. Because this is going to be a language feature the CLR doesn't know.
If you turn it on, yeah. Interesting feedback. We should see if that can be an error. I don't know if you could do it and make it an error. I think there's just a little concern, but that's an interesting idea. So if you know it's wrong, make it an error. Yes.
Okay. Okay. Yes. How would this work with a public facing API? Once you turned it on, if you didn't have string question mark, your public API would be, if you are calling this, you have to have it turned on.
And it's in a public API, it could only be called, right. Oh, if you're actually, like say, an ASP.net, right.
Right. So the question is if it's a public, yeah, and it's called through reflection. That would be a good question to add on this proposal. I don't think that's been looked at. Right. It's a compilation thing, not a runtime thing. So that could be an interesting question.
And then finally, for cases where the static analysis doesn't get it right, we have what's colloquially referred to as the dammit operator, which is I know this isn't null, dammit, just work. A couple different things for small but useful is I've got about 10 minutes left.
Private protected will probably try to come back. If you really have nothing to do for weeks, you can read the debate about that particular feature. The idea behind this is CLR supports this. Right now, if you put protected internal on anything inside a class,
it is accessible to anything in the same assembly or derived from that class. Private protected would mean it would have to be derived from that class and in the same assembly. There's a lot of concern over exactly what that should really mean. And then the idea of local functions. This is a pattern both for enumerator methods and for async methods
and in many other cases. The idea that for an enumerator method, what I would like to be able to do is check my parameters and throw an exception immediately if it's wrong. Similarly, for a public task returning method, I want to check my parameters and synchronously throw an exception
if it's just plain called wrong. In order to do that today, you introduce a new private method which adds something to the class, looks like it could be called from anywhere, but in reality is only going to be called from this one public facing method. So why not put it inside here, declare it here,
and then return the iterator method. So the pattern would be do my parameter checking in a synchronous task returning method or in an enumerable of T standard method and return the enumerator method or the asynchronous task returning method
if rudimentary checks have passed. Simple but useful. Would you be able to nest them? That's just a function. So why not?
Yes. Yes. Okay. Yes. I'm not sure the compiler can do that kind of static analysis.
Okay. You'd have to test it through the public method, right? That method would not be callable outside of that. And in fact, this would likely be implemented either using a delegate or a closure
depending on what the inner method does. Performance and interrupt. Last things. These are super useful if you care. Okay. So first of all, let's look at the idea
of making a ref return. So in order to increase performance rather than copying a large object, let's say I want to return a value type by reference. So I'm going to return a reference to some internal storage rather than copying it.
Once again, this gets back to that immutable idea, but it's more about performance here. I have a large internal data structure. Here's a reference to it. I would have to declare the variable with the ref keyword. So ref var a equals ref get asteroid, and then I can do anything with that reference
to an internal data structure. Yes. Game people love this because they're trying to avoid copying. Otherwise, it's getting, well, okay. I don't know if I'd ever use it. The interesting thing the compiler has to do here
is trace things so that you cannot return a reference to an object that has a shorter lifespan than the returning construct, and it has to transitively watch that. The idea of getting slices.
So let's say I have a large multidirectional or multidimensional array, and I want to slice it. At the moment, this would just be a horizontal slice. So I want to do something with matrix algebra, and I want the third row of a matrix. Here it is by reference, and you have a slice, okay?
Once again, the idea is to avoid copying, avoid doing a lot of marshaling if that happens to be a native structure. Thoughts? This is the opposite of immutability, John.
performance of the code, because for you, in iOS terms, what does that end up as? Because I'm used to the first one is going to be a vector. The slice that you would get would still be a vector.
You're getting the one dimension, yeah. What if I use length of it? You should get the right behavior. It's meant to create a slice where the internal storage is the same. So it doesn't copy the vector?
Yeah, that's what it's going to have to do, yes. What if it gets resized? OK, you would have a reference to the original copy, right? And that gets back to the first ref part, where if I'm going to do something like this,
the compiler is going to have to ensure that the thing you're pointing to lives beyond that time, right? So the scenario for this, right. Well, no, the scenario here is primarily that these are going to be fixed buffers. It's used for performance reasons. The primary audience for this is people doing games.
XNA programmers love this concept because they avoid a lot of copying back and forth between native and non-native structures. Yes, or part of a row. Doesn't have to be the whole row, but yes, right.
Yes, it is. This is a very niche feature. It's probably not that expensive. Yeah, nope.
So far the plan would not require CLR changes. OK, do I have much of anything left? Yes, I might. So, OK, all right. Yes, it does. The second example is meant to say, yes, you
can map managed memory onto an unmanaged block. Yes. Yes. Right. Now we get to the big interesting question that's going on with the team right now.
So right now we have C Sharp 6, released with Visual Studio 2015, and so on. The language and the compilers are open source. There is nothing that has to tie the compiler and the language version to a major Visual Studio release. So with the features that we talked about here, or with whatever comes down the pipeline,
is there any reason not to just go, here it is. Use it. And here's a patch release of whatever we're doing. Or can we release a new version of the language whenever it's ready? Hey, here's record types. They're there. Is that better or worse? And what would that vehicle look like?
So who here would like to see it stuck with Visual Studio? So I'm going to get a new version every year. Every two years it's going to be C Sharp 7, C Sharp 8. OK. Yes, I know. Two years seems like a reasonable time. Right.
OK. If you don't depend on Visual Studio, the tooling might not be there. And the Roslyn APIs for analyzers and so on. That whole ecosystem may not be there. So slow releases give me a new version of the language with all kinds of stuff whenever. OK. My compiler is something like a NuGet package.
I got a new one this week. OK. That's interesting discussion. So far that's actually been much more toward, no, no, don't give me new language stuff every day. That's interesting to think about. As you keep thinking about that, send me email, do something. I know it's one of the big questions.
I'm totally out of time. I will be right out here to answer any questions so that the next person can set up. I'm going to make one real brief commercial. I work on a charity called Humanitarian Toolbox. We write open source software to support disaster relief efforts. If you want to check out what we're building and participate, we would love to have more participation.
And then finally, this is me. If you want to take a picture of this one, this is how to reach me any time later. If you have any other questions, I've included where the main Roslyn repository is. Remember, it's we now. We all get to participate in these discussions. Check it out. Look at the different issues weighing on the discussions.
If you're really adventurous, check out one of the feature branches and play with, say, record types or pattern matching, which got a lot of discussion. And yes. You'll have to build it.
Yes. Yes. But then you'll have it. But you could download, say, the record pattern. It is open source. Yes. Yes, you can. Right now, there are no commitments for exactly what will be in the next drop.
That is correct. But you can certainly play with it, participate, and experiment. And thank you very much.