Play by Play - The C# Q&A, Episode 1
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 133 | |
Author | ||
Contributors | ||
License | CC Attribution - NonCommercial - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/49615 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
NDC London 2016103 / 133
2
6
10
12
15
17
23
24
28
30
31
32
35
36
39
40
43
44
45
47
51
52
55
58
59
60
61
62
63
64
67
69
71
73
74
75
82
84
86
87
97
103
107
108
111
112
114
115
117
120
123
126
128
129
132
133
00:00
Software developerLambda calculusInternet forumCategory of beingWechselseitige InformationTable (information)Query languageExecution unitCore dumpLevel (video gaming)CodeMultiplication signReduction of orderMatching (graph theory)BitExpressionDemosceneCompilerQuicksortExtension (kinesiology)Semiconductor memoryInterface (computing)Stack (abstract data type)Repository (publishing)Order (biology)DatabaseBuildingDynamical systemLink (knot theory)Query languageCategory of beingSocial classWeb applicationWeb pageProjective planeBlogDifferent (Kate Ryan album)Execution unitSinc functionKeyboard shortcutBuffer overflowOperator (mathematics)Object (grammar)Expandierender GraphType theoryExistenceSyntaxbaumLibrary (computing)Web 2.0String (computer science)Visualization (computer graphics)RepetitionSequelStreaming mediaMixture modelNeuroinformatikPoint (geometry)Sampling (statistics)Combinational logicComplete metric spaceDataflowUnit testingComputer animation
06:43
Software developerAerodynamicsView (database)Inclusion mapBitRight angleInterpolationString (computer science)Extension (kinesiology)CodeTouchscreenFile formatVariable (mathematics)DigitizingSocial classQuery languageResultantInheritance (object-oriented programming)NamespaceCompilerEnumerated typeQuicksortStatement (computer science)ExpressionParameter (computer programming)Multiplication signInjektivitätC sharpCompilation albumCountingRevision controlPredicate (grammar)NumberMessage passingException handlingLink (knot theory)CurveEqualiser (mathematics)Direction (geometry)SequelSystem callGame theoryGodFormal grammarForm (programming)Interpreter (computing)Electronic mailing listVideo gameMatching (graph theory)Cellular automatonComputer animation
13:20
Software developerInclusion mapVideo game consoleFile formatQuicksortMereologyDigitizingCodeTable (information)Flow separationNumberTerm (mathematics)Representation (politics)Order (biology)DemosceneProjective planeCompilerGoodness of fitCASE <Informatik>Parameter (computer programming)Buffer overflowStack (abstract data type)Graphics tabletString (computer science)Poisson-KlammerElectronic mailing listInterpolationAnalytic continuationVariable (mathematics)BitState observerPower (physics)Compilation albumSequelInterpreter (computing)Different (Kate Ryan album)InformationSpeech synthesisComputer animation
16:44
File formatForm (programming)Video game consoleEmpennageSoftware developerDemosceneSource codeString (computer science)MereologyProcess (computing)CompilerLine (geometry)InterpolationCompilation albumPower (physics)TouchscreenFunction (mathematics)CASE <Informatik>Interpreter (computing)AreaInformationComputer animation
17:37
Software developerNumerical digitFunction (mathematics)String (computer science)Run time (program lifecycle phase)VarianceIterationInterpolationEnumerated typeLine (geometry)Loop (music)Reflection (mathematics)Installation artProjective planeElectronic mailing listTouchscreenDigitizingFile format.NET FrameworkComputing platformCompilerExpressionSpeech synthesisRight angleMultilaterationGoodness of fitStack (abstract data type)Multiplication signSocial classWeightIntegerGraphics tabletCodeQuicksortVideo game consoleBuffer overflowOcean currentRevision controlPole (complex analysis)Game theoryOperator (mathematics)Exception handlingPoint (geometry)WebsiteDifferent (Kate Ryan album)ProgrammschleifeNumberCASE <Informatik>Matching (graph theory)Numeral (linguistics)PlanningBit rateInterpreter (computing)Formal language
22:36
Software developerService PackCompilerAuthorizationMoment (mathematics)Point (geometry)Different (Kate Ryan album)Loop (music)Electronic mailing listLine (geometry)Enumerated typeWeightBitSource codeCodeCodeVisualization (computer graphics)Interior (topology)IterationNumberBasis <Mathematik>Compilation albumType theoryState of matterMultiplication signNumeral (linguistics)QuicksortSweep line algorithmPerturbation theoryEqualiser (mathematics)Event horizonComputer animation
25:58
Software developerElectric currentVideo game consoleSource codeSocial classInstance (computer science)OvalC sharpBitQuicksortGame controllerPattern languageLoop (music)MathematicsStructural loadType theoryOcean currentData storage deviceMultiplication signDifferent (Kate Ryan album)Software bugMathematical optimizationEnumerated typeView (database)Run time (program lifecycle phase)Point (geometry)Numeral (linguistics)CASE <Informatik>Configuration spaceImplementationUniverse (mathematics)ResultantSource code
28:11
Software developerSocial classLibrary (computing)Table (information)Multiplication signCompilation albumCompilerEnumerated typeCodeOpen sourceFactory (trading post)Binary fileVariable (mathematics)Category of beingLibrary (computing)Data storage deviceAbstractionVolume (thermodynamics)Range (statistics)ResultantNormal (geometry)AdditionCodeMathematicsField (computer science)Type theoryEncapsulation (object-oriented programming)Inheritance (object-oriented programming)C sharpBlogString (computer science)Sampling (statistics)QuicksortDeclarative programmingJava appletView (database)Constructor (object-oriented programming)ExpressionNeuroinformatikComputer programmingRevision controlInterior (topology)NumberDigitizingDifferent (Kate Ryan album)Projective planeFunction (mathematics)Social classBitMobile appRandomizationRight angleGod2 (number)Hydraulic jumpClient (computing)System callException handlingExistenceLink (knot theory)Position operatorFormal languageCondition numberOperator (mathematics)VarianceIdentifiabilityImplementationBuffer overflowSoftware bugStack (abstract data type)Bounded variationChainRecursionApplication service providerSoftware frameworkAddress spaceAttribute grammarElement (mathematics)Loop (music)Latent heatLocal ringObject (grammar)Logical constantGoodness of fitGreatest elementSinc functionLine (geometry)Electric generatorInsertion lossRegular graphExterior algebraTerm (mathematics)Level (video gaming)Control flowSource codeUniform resource locatorInstance (computer science)SyntaxbaumZoom lensLambda calculusClique-widthAuthorizationTable (information)Physical systemTouchscreenCASE <Informatik>SpeicherbereinigungDynamical systemRun time (program lifecycle phase)Web applicationDisk read-and-write headElectronic mailing listComputerPoint (geometry)Process (computing)Bit rateEvent horizonWeb 2.0WebsiteWordScripting languageAreaReading (process)Universe (mathematics)Classical physicsWeightFamilyComa BerenicesSineThomas BayesLetterpress printingToken ringMoment (mathematics)Self-organizationMetropolitan area networkComputer scienceRule of inferenceWeb pageCentralizer and normalizerUnicodeLogicLimit (category theory)Personal identification numberMaxima and minimaAngleCompass (drafting)Military baseFerry CorstenDigital photographyEmailMetreComputer simulationInterface (computing)Speech synthesisBuildingSemantics (computer science)Cartesian coordinate systemFitness functionPoint cloudDressing (medical)Shared memoryExecution unitPerimeterTape driveDemosceneSystem dynamicsSource code
Transcript: English(auto-generated)
00:06
Thank you guys for getting up early and coming to our talk today. I wanted to do a quick introduction and then we'll get straight to the code. I'm Rob Connery, this is John Skeet, of course, that's Scott Allen. Every year at NDC we try and do something a little more fun-oriented,
00:21
something live on stage, usually called a cage match. This time we're calling it play-by-play. The idea is that we're going to answer some questions from Stack Overflow live. Well, not live on Stack Overflow. We were taking questions from Stack Overflow. They have code samples. Either one of them does not know what the other has answered.
00:41
So I've cherry-picked some questions. I said, okay gents, answer the questions and we're going to see if they match. And if they do, hooray. If they don't, we're going to have some fun. So we'll get right to it. Dan, put on Scott. Switch, Scott. There we go. Sure. All right, so Scott, do the first question.
01:01
And what's your Stack Overflow rep again? 2000. About 2800 points, I think. All right, well be kind to John, will you? Well, one of the first questions that Rob picked out from Stack Overflow was a question from 2008 from John Sheehan.
01:20
And this was the question. I found an example in the Visual Studio 2008 examples for Dynamic Link that allows you to use a SQL-like string. So you can see here, order by, and I can specify a property name as a string name. Unfortunately, this method included only works on the i query of T.
01:41
So basically John's question was, how can I use this Dynamic Link library, Link being L-I-N-Q, if I have an IEnumerable collection in memory, just in memory data. And I thought this question was actually interesting because back when Link first came out, I started using Link to SQL on a project. And Link to SQL, of course, would represent the database
02:03
as IQueryable collections. And so it was easy to build data access classes that could query the database by building, let's say, a repository or an employee data class that returns IQueryable collections. But then when you get to unit testing, you want to have something that implements the same interface
02:21
and still returns IQueryable. But you want to do that within memory data. How do you go about that? Well, that's when I was, back then, Link to SQL, I was digging around. And I found that the easiest thing to do, actually, this is the easy answer I'll give you first, is to, given an in-memory collection of movies, let's say,
02:45
just use this Link operator as queryable. And that makes your in-memory data appear as an IQueryable of T. And then if you have a library that only supports IQueryable of T, you can start using those operators against it. Can we zoom in a little bit? Sorry.
03:00
Sorry? Can we zoom in a little bit on the code? Oh, yeah. There you go. So that's one possible solution. That is exactly the solution I came up with as well. I haven't touched the keyboard since Scott was talking. It feels like as queryable. Dan, can you switch to John, please? Here we go.
03:20
So yeah, I have a slightly different example with people of John, age 39, Rob, age 78, Scott, 25. And then the exact example from the question, and it just worked. It was my answer making you sassy. And this was having never, I think I may have used,
03:41
have you used Dynamic Link before? No. The weird thing is that it says on the project page and whatever, and I remember I have tried using it before, and there's been a link to a blog post, and the blog post hasn't existed, but you can find it somewhere else, and then that links to a code project project that doesn't exist. These days, it's in Nougat. It's fine.
04:03
But it says it's linked for the dynamic type. Now, I haven't actually tried using this over an expander object or anything, so who knows whether or not it would work. It feels like it's really string-based link more than dynamic link. But yeah, it did just work. It's cool.
04:21
You had some second code, though. Well, I did have a second one. You re-implemented Dynamic Link. No, no. Well, not exactly. But going back to 2008 when I was working with link to SQL, I was building web applications, and a common requirement in a web application is you let the user select how they want to order a particular data grid. And with link to SQL, it's hard to pass in a variable to the order by clause.
04:45
Dan, switch to Scott, please. Sorry. Yeah, so this was something I had kind of faced many years ago. And back then, it was easy to find a decompiler that would give you a little bit of decompilation
05:01
of what the syntactic sugar of C Sharp was really producing behind the scenes when you had an expression of T, and it was building your code as data. And so I just put together a real quick example to show you how easy it would be to do something like this, which is I want to take these movies and order by or order by descending
05:21
and actually pass in a string. It's not nearly as rich, I don't think, as the Dynamic Link library. But what you really need to do there, if you were to, let's say, just write this code and not have some of these extensions that I have, you would be able to use ReSharper to codegen a method
05:44
that looks like what you would have to implement to pull this off, which is essentially, again, what I did last night, and I accidentally didn't comment on the whole class. But it would be a method that looks like this, order by descending. It's an extension method for IQueryable of T. It takes a string, and down here, I can build a sort expression.
06:05
This is what the C Sharp compiler would actually do behind the scenes if you had an expression of T like M goes to M.title or M goes to M.ID or M goes to M.rating, whatever like that. So it's only a little bit of code to inject that,
06:21
and it can actually work with something like Link to SQL or the Entity Framework because you're actually building the expression tree that it has to analyze to convert this into SQL. One of the things we want to do as well is to make this more of a live session. So if you guys have any questions, raise your hand, shout it out. We don't have to sit there all quietly, so if anybody has any questions at this point, anybody, don't be afraid.
06:45
I'll make sure John's nice to you. Yeah, do just shout out. Do you have something else to show? Yeah, so I was just thinking while you were saying about decompilation, I thought I'd show an interesting fun little trick that you could do even with query expressions.
07:02
So you were saying about sort of seeing what's going on. Yes. So suppose you have this list of people, and you're going to do var youngPeople equals from person in people, where person.age less than 65, select person.name or whatever,
07:24
and you want to see what's going to happen, and we're just going to write out the count of that. And you would kind of expect that that's going to use enumerable.where, and normally it would, but the way that the C Sharp compiler finds extension methods,
07:41
it will first look in the namespace that your class is in and then the parent namespace, et cetera, until it gets to the top. So if you happen to put your own extension method called where that does the right thing, and we can even just delegate to the original where.
08:05
Oh, we can't easily see the original value if we don't implement it ourselves, but that's easy enough to do for where.
08:26
Use some C Sharp 6 fun. result equals predicate item, so let's put that there,
08:40
and then if the predicate matched, we can return the item. Okay, so this is now just a version of where that happens to log everything as it goes along, and now we can see the count if we run this code.
09:06
We will not see what we expected. Oh, it's so embarrassing when this happens. How about we make this an extension method in a static class? That would be really useful. Right.
09:21
And now, yes, hooray. So we can see that the compiler's just picked up. That's an extension method that happens to match, and it sort of takes precedence over enumerable.where. So I'm only saying that because you were saying, how do you work out what's going on? This is just one extra way that you can sort of step into getting the middle of link expressions.
09:42
All right, should we move on to the next question? Yeah. Okay, before we do, anybody have any questions about what John or Scott has talked about? Or what Scott said. Or what Scott said, yep. Okay, so let's skip actually down to the last one. We'll throw you guys a curve ball. We'll skip down to the last one, which is C Sharp 6 stuff. Oh, yes. Did you read that question?
10:01
Scott? Yeah. All right, well, we'll actually start with John this time, and do you know which one I'm talking about? I assume so. This one, yeah? The format, the... Yes. Yeah, yeah, yeah. Okay, so do me a favor, summarize the question. Okay, so the question is... Yeah, I don't have the link. Do you have the question up? I have it on the screen.
10:21
Yeah, okay. So then if we can switch to Scott. Yep, there you go. Fantastic. Okay, so the question is that we're wanting to format two integers, and hooray, with C Sharp 6, we can do that with string interpolation, which I was initially slightly skeptical about, but really it rocks, particularly for exception messages.
10:42
It's just so handy. But the problem that the questioner has is he wants to specify the format and the number of digits in each of these, and that format is itself variable. And this is in some ways, you know,
11:01
he happens to want to do this with string interpolation, but this isn't a new problem. And honestly, there is no very nice solution to this. So before we switch away, does everyone understand what the question is? We want to use one variable to say how many digits
11:23
to format another variable. The fact that we've got a pair of these things to format is kind of irrelevant as well. So everyone happy with that? Okay, Dan, if we could switch to John's screen. Fantastic. Okay, so the closest I came to this is to say, well, you know, we don't need to,
11:41
the original question had some duplication of code. We can at least have a method of format saying what the value is and how many digits. We could potentially make that an extension method instead, and in fact we could just do that in here with digits.
12:03
So we can now do x dot with digits, x digits, and y dot with digits. And, you know, okay, it's in a string interpolation expression, but it's still just plain C sharp. You can do almost anything in string interpolation.
12:23
And this will, I hope, give the right answer. Yeah, so the first value is interpolated to, sorry, is padded to seven digits and the second one to three. But fundamentally the interesting bit to me about this
12:40
is that we're trying to use something that's variable in somewhere that string dot format doesn't like you to have variables. And this reminds me strangely of SQL. So it boggles my mind that we are still facing SQL injection attacks.
13:01
How long have we had parameterized SQL for? I started using JDBC a long time ago and I'm pretty sure prepared statement was in there right from the start. And my guess is that parameters existed before that. Just yesterday I was answering a question to you. Why doesn't this SQL statement work? Well, it turned out he had a comma before his where clause,
13:22
but really the problem, the bigger problem was that he was putting the value straight into the SQL. I said, don't do that for goodness sake. Okay, on my next project I'll investigate. No, do it now. Do it now, please. For the love of everything, just do it now. I get quite passionate about this.
13:42
But you can't do that everywhere in SQL. So if you take the table name as a variable, in fact, you're very clever, Rob. See, Rob had planned all of this that thinking about the ordering in the previous question,
14:00
an order by clause, you can't parameterize that in SQL. You can't say order by bracket parameter name and then put parameter is name or age or whatever. And likewise, you can't specify the number of digits to pad it to. In a string dot format thing, it's expected to be sort of part of the code rather than part of the values that the code works with.
14:23
And that separation of code from values is something that's been quite interesting to me for a number of years in terms of separating the representation of something from its actual value. I'll talk about that more later on for those of you who come to my explaining problems talk.
14:42
But this sort of understanding how we work with data and which bits of data. I love the idea of code as data, data as code. But you really need to understand which bits are which and which bits whatever you're working with is going to interpret. And string dot format just doesn't have a way of saying take this parameter and that's part of the formatting
15:03
for this other thing. So I think rant over and let Scott have a talk. No, that's just fine. This is where Scott finds some miracle that completely kiboshes what I just said. No, not at all, not at all.
15:20
But my first observation about this question, it was the last question on Rob's list, and I realized there were at least a couple questions in this list where I think people were just sort of tripped up by the syntactic sugar that C Sharp has been adding over the years. So syntactic sugar being the C Sharp compiler gives you a feature that allows you to do something you could have done before
15:40
but it does it with a different syntax or fewer characters. And string interpolation is one of those features. Dan, switch to Scott, please. Yes. Sorry, continue. And I was trying to reproduce what the Stack Overflow question was about, and I imagine that this fellow had code that was something like this
16:05
using string interpolation where you're trying to say, yes, I want to take x and format it with this variable, and I want to take y and format it with this variable. And on the face of it, you might think, well, that might work unless you know what's really going on behind the scenes
16:22
with the C Sharp compiler, and that's where a decompiler can be useful. Or even the compiler in this case. You can see just by the syntax highlighting and by the warning x size and y size aren't being used because they're not being evaluated as part of it. Exactly. And I keep a little tool installed called ILSpy,
16:44
which is just one of many decompilers. Other decompilers are available. What's that? Other decompilers are available. Other decompilers are available. But I'll tell you there's pros and cons to each. Some decompilers do such a good job recreating the source code that you don't actually see some of the trickery that the C Sharp compiler is doing.
17:01
We'll come back to that. ILSpy, fortunately, doesn't try too hard in some areas. So in this case, if I call your attention here to the middle of the screen, let's see if I can also draw a line here. You can see, yes,
17:21
what that string interpolation was really doing behind the scenes was doing a string.format, and you can see that's all textual information, right? x size is not a variable there. It's part of a string literal, and that's why when you run that particular snippet of code, when you try this, you do not get maybe what you would expect.
17:41
You get, this is the output of that particular method, x size, y size. That's kind of sucky. Yeah, I don't see... That should go bang. What's that? String.format should say, I have no idea what x size means as a custom string. You would think you might get a runtime exception,
18:00
but apparently, no. I couldn't find a way around this, but to build the format string to use to format the numbers. So just a slightly different variant on what John did, which is use string interpolation to build the string, let's say, D7,
18:21
and when you pass that in to the two-string method of an integer that says I need seven digits, and if there's not enough digits to make seven, then just pad it in the front with zeros. And so this would put out the right output. One of the things I find interesting about this question is it's not something that you can fix with evil code.
18:43
I know I can't even remember where we did it, Rob, but I know we've previously discussed sort of hacking into the string interpolation that's in C-sharp 6, which you can do only if you're using a version of .NET prior to 4.6 or 4.5.2 or something.
19:02
Because if it's available, the C-sharp compiler will use a cunning class string, a formatable string builder or something. And if you're not on a platform that supports it, but you happen to have your own class that does it, then hey, you can do your own funky weird things.
19:22
But in this case, because it's really the syntax of the language, the compiler is saying, nope, anything before a colon, that's an expression. Anything after the colon, that's just text. Even with evil code, you can't hack this one. There we go.
19:40
I also did it at Nord-evCon last year. I recycled, you know. It's greener. Yeah, but thank you. Hey, people watch it. I know they do. It's exciting. Yes. I'm speaking of Pluralsight. The comment was that what John just was saying was on a C-sharp 6 Pluralsight thing we just did. We are actually recording what we're doing here right afterwards,
20:01
and it's going to be on Pluralsight as a play-by-play, actual play-by-play later. So I just want to plug Pluralsight. Thank you. Is there anything else that you guys wanted to add to that? No, I think I'm good. No, I think I'm good. All right, any questions? Come on, somebody's got to ask a question. You guys had your coffee. Yes.
20:22
The question was, what's the rant that John wanted to come back to? This time not to run, actually. More an extra question. Shall we insert an extra question now? Take it away. So I don't have ILSpy installed. I do have Reflector installed. There was a recent Stack Overflow question, which was, I have some code, let's just...
20:43
Can we flip over to John? Yes. So let's add this as a new project. Decompiling loops. So someone said, hey, I've got... He had a single method.
21:00
Sorry, they had a single method. I don't know whether it was man or woman. One while loop and one for each loop. So let's just put in list in values. And I'll do the same with a for each loop.
21:22
And they were just putting them out to the screen. Item in values. Console.right line item. And then someone was saying, well, for each loop is just syntactic sugar,
21:41
so using var iterator equals values.getEnumerator. Sorry, I call it iterator because it's an iterator in every useful way. Why the .NET framework decided to use enumerable instead of iterable? Particularly when it means that when you've got enumerations, which are not... Enums are not in any way like iterables, but...
22:02
Sorry, I said I wasn't going to rant, didn't I? While iterator.move next. Console.right line iterator.current. So we can create a new... What this does is obvious and boring.
22:24
While loop values and for each loop values. I will run it just to make sure that I really haven't screwed up this time. But the question I was saying, okay, I decompile these two,
22:41
and the decompiler is able to tell which one was a while loop and which one was a for each loop. How? I looked at the IL with IL-DASM, and they looked the same to me. So yeah, go for it, answer the question. I got there in the end.
23:00
And what does IL-Spy do? Wow. Oh yeah, so you're saying what does IL-Spy do? This is where it would be really handy to be able to share this code straight over. I know. Do you guys have airdrop? Just kidding. So let me try to recreate, I guess, what you had first. I wasn't paying attention.
23:23
We had, what was one method? While loop and for loop, for each loop. Ah yes, while loop takes some IList of, let's say int. I took a list of int. You could take an innumerable of int, it will give different code.
23:47
And a for loop. Ah ha. Trying to remember syntax this morning. Dan, can we switch to Skype please? Oh yes. Here we go. An IList of int, some source of numbers.
24:00
Oh, IList of int. Again, this is going to be interestingly slightly different. Oh sorry, you were taking all this. I took a list, but let's go with that for the moment. Okay. And then we can see whether the audience would guess what's going to be the difference between that and taking a list. For each item in source, we want to just console dot write line the item.
24:25
And well as down here, I want to say the enumerator equals source dot get enumerator. That's the first mistake that the questioner made. Oh. We need the using statement. We need the, oh, on the enumerator. On the enumerator. Ah ha.
24:41
Gotcha. I think I, that gives me a bit of a clue. Yeah, the C Sharp compiler will automatically dispose of any I enumerator of T. I still have yet to get hold of a C Sharp 1.0 compiler as opposed to a C Sharp 1.2 compiler. I'm just, I'll talk while Scott codes because it gives him a bit more time.
25:03
I am somewhat convinced that one of the very few differences between C Sharp 1.0 and C Sharp 1.2, I don't know what happened to 1.1, but this was the difference between Visual Studio 2002 and Visual Studio 2003, is when the compiler will dispose of things used in a for each statement,
25:23
the iterator used in a for each statement. It's very hard to get things running with actual dot net 1.0, rather than something with a service pack that's going to potentially have the C Sharp 1.2 compiler. I have looked for references for this behavior on the net and I found plenty of them.
25:43
Unfortunately, I'm the author of all of those references. So I have claimed this many times. At some point there must be a reason why I've claimed it. I suspect it's that if the, if this is a for each loop that isn't using I enumerator, but is using some type that has the appropriate move next and current methods,
26:04
or members, my guess is that in C Sharp 1.2, it detects whether or not it implements iDisposable at execution time, because the value could be of a type that implements it, even if the compile time type doesn't, whereas C Sharp 1.0 didn't.
26:24
But I can't prove it, and it really bugs me. Okay. Okay, while you were talking, I'll spy on looking at the for loop, and it seems to have detected that that was a for each somehow. And we can also take an IL view of that, but just to show you the while loop,
26:42
it was able to tell that that was a while loop. Interesting. Yes. And we could switch over to the IL view and just eyeball it really quickly, but here we're getting the enumerator, blah, blah, blah, blah, blah. Okay, let's just take a look at the other one real quick. Also getting the enumerator.
27:01
I detected some sort of pattern change here in the middle, which is... So what I certainly noticed was, yeah, it is the same here. If you look at, in both cases, there are still lock and load lock. Not one things, but they sort of move around.
27:25
And this was the sort of IL detail that the questioner said, you know, the IL looks the same to me because it's functionally exactly the same. But there's no reason to store and then load. But the for each loop will do that with the result of get current,
27:45
but not of move next, whereas I think your manual while loop, when compiled, my guess is you're compiling in a debug configuration, because that makes a difference. All of this stuff, and then there's weather optimization. I did all this from the command line where you've got a little bit more simple control.
28:04
But the other thing, can I have a look at your while loop again? Let's see if we can confuse IL Spy enough. Right, okay, so the other thing that I suspect is different is that you're using enumerator.current there,
28:22
and I believe that the C Sharp compiler syntactic sugar effectively does var item equals enumerator.current, and then uses item. Oh, isn't it always fun using someone else's computer? It is, I can put it in for you.
28:42
Is Bill here by any chance? No? Bill? Bill Wagner, one of the most amusing times was when he'd given a talk about stunt coding in C Sharp, and he could see me itching at the front for the whole talk, but particularly near the end. There was a way that I could just make it more beautiful,
29:03
and so I said, last five minutes, Bill, can I just try something? And he had Code Rush installed, and I hadn't used Code Rush. Oh, boy. It was really, really interesting, so I couldn't get anything to work. Anyway, so what have we got now?
29:23
With that small change, are we now fooling it? Because we should be able to make the... Yeah, if I switch back to the C Sharp view. C Sharp, and has it reloaded everything? So it sees a 4H for the 4 loop, and a... Yeah, we have fooled it. The while loop is now a 4H loop. So yeah, it really is the syntactic sugar for a 4H loop
29:44
is something you absolutely can express in straight C Sharp. There are other bits of C Sharp syntactic sugar that are relatively tricky. I can't remember if the lock is still that or not, but there used to be some things where it would do some funky bits,
30:02
like async certainly has this. There are things that async uses where the C Sharp inserts what's effectively a go-to, but a go-to in a way that you can't put in regular C Sharp code. You can't go to the inside of a loop or something like that. But even then, the C Sharp compiler has restrictions because of what IL allows.
30:22
You can't go to an arbitrary place within a try block or something like that. So yeah, there are bits of syntactic sugar that can't be represented, but it looks like 4H isn't one of them. Yeah, that's a perfect example of what I was talking about. Decompilers sometimes don't faithfully give you the exact source code that someone wrote out.
30:40
Right, exactly. Precisely because in some cases... Maybe this should be a code review tool. If decompiling your code gives you a simpler solution, then just replace that. Does anybody have any questions for John or Scott out there?
31:01
Anyone? All right. You guys want to move on? Yep. What's up next? Let's see. I guess it's Scott's turn to go first. And we are on Scott. Good. How about we keep doing the C Sharp 6 stuff? Always. Yeah, so go down to the bottom there. And the question from GnomeB.
31:22
There we go. Simple one. Yeah, this is another example of where I think perhaps syntactic sugar has tripped somebody up. They declare in C Sharp 6 an auto property with only a getter, so you cannot write to that. But the person was confused a little bit. When they write a constructor, they can still do an assignment to foo
31:42
even though there's only a getter. And I think, again, maybe if you've only been around C Sharp since auto properties were around, you might think that when you declare public int foo with a getter that you're declaring some sort of storage location in the class. But those of us that have been around before automatic properties
32:02
know that there's always a backing field behind a property because at the CLR level, a property is really just a method call and it still needs some storage location to read from. And that's, again, a place where I went to something like IL Spy. This is how I would demonstrate it to someone
32:21
what was going on behind the scenes. That user class, once I click on the right location, I'll zoom in on this. That's what an auto implemented getter only property would look like. There is a backing field that the compiler generates for you. It uses some wacky names so you can never actually
32:42
access that backing field from source code legally. Unspeakable name. I love that term. I don't know whether it's ever been official or whether Eric Lippert just made it up, but the idea of an unspeakable name is fantastic. Unspeakable name. But that's why it works because the compiler will allow you to set that backing field on the constructor
33:02
and only inside of there. But there is a field there. Yes, I sort of wanted to ask the person who asked this question if they saw a read only field, whether they would expect to be able to set that in a constructor because it's read only so you can't write to it.
33:22
Well, yeah, you can in a constructor. I asked for this feature in about 2004 or something. It's been so annoying that writing read only properties has been a pain for so long. Sorry, it's fantastic that it's finally there in C sharp 6.
33:43
I have also had a feature request in my head of instead of it being an auto prop, Dan, if you could switch back to John's. So imagine this will be a painter type
34:02
and not syntax highlight properly, I'm sure. But I think I previously had proposed syntax of something like public string foo and then we'll have a getter that returns foo. And we just have, in fact we don't give it anything else.
34:27
So the idea of declaring a field within a property declaration. So it's only available, that field is only available within the property declaration. And then you could have multiple fields
34:40
that could update themselves. Now, exactly how you would write to that field, I don't know. Within maybe everything declared. It would be sort of nice if everything declared within properties were available within the constructor in the same way because we could have this as read only string foo.
35:00
But then this looks like it's scoped to these braces. So maybe you could then do within the constructor, see what I mean about everything screws up when you start using invalid syntax. It's a real problem.
35:20
Oh, just get over there. You could do foo.foo equals whatever, maybe. Something like that. But then, yeah, you could have a property that relies on a few variables and you could have them all definitely there. I think I was asking this before
35:40
automatically implemented properties came along at all. But this would also mean that you could isolate property backing storage from everything else in the class. So sometimes auto props don't work. Suppose we have an int age.
36:00
You never have an int age. You have a local date. This is your date of birth because you're using JODA time, of course. And you have an int age. Get return age. Fine. And set if age less than zero.
36:21
Throw new volume internal range exception, et cetera. Sorry, value. And so obviously you can't do this with an auto prop. Read only auto prop's fine because you're not actually going to be setting it anyway.
36:41
But if you want some validation, you can't use a normal auto prop, which means that the rest of the code in that class has access to the raw fields. So if you want encapsulation to the max, then you're kind of in trouble because anything could write an invalid value to age. Whereas if you could declare the field within the property
37:06
and maybe say, hey, that now can't be written even by the constructor. Nothing outside the property can access that field. Then it gives you just that little bit more encapsulation. So yeah, that was a random feature request that I'm never expecting to actually happen
37:21
from a long time ago. Cool. Is that it? Yeah. All right, any questions out there? No one? Man, you guys are, got to wake up. All right. Okay, hang on. Everyone, right. Stand up. Oh, dear God. Stand up.
37:40
All right, and just five seconds of jump up and down. Okay, right, you can sit back down. If there aren't any questions in call for now, we're going to do that again. Okay. Thank you for that. Get people awake.
38:00
I've got a first session after lunch. Yeah, I think I'm going to be doing that again. All right, good enough. Should we move on to the question about lambdas? Yeah. I would like to, yeah. Okay, so let's see. Scott started last time, so John, you still have the monitor. Actually, Scott, can you show the... Yeah, yeah, yeah. I can switch to Scott, please. There we go. Okay, this one's a little bit longer.
38:21
Sorry about the code formatting on there. I couldn't get it exactly right. Take it away. Yeah, did you want me to summarize that? Oh, yeah. Sorry, sorry, sorry. So someone's writing a link expression like U goes to U.userID, and what they really want to know is what is the name of the property
38:42
that is being accessed. What is the string value of that user ID? And in the post, they included a copious amount of code to figure that out. The problem being, what they realized was that if U goes to U.userID, and userID is an int
39:01
that builds one type of expression that you have to massage a certain way, but if U goes to U.userName, something that's a string, you get a different type of expression, and they just wanted to know if there was an easier way to figure out what that is, what the name is.
39:22
And then was I up? Well, go ahead, I guess, myself. I think John's answering a question. Oh, yeah, sure. I mean, he literally is. He's literally answering a Stack Overflow question on stage. Don't let us bother you. Yeah, I couldn't exactly come up with a better answer.
39:43
I think I came up with maybe slightly better code, but if I want to know what is the name of this property, and let me just set this as a startup project and make sure it works, I should be able to get the output. You are referencing name and you are referencing ID that appears to work.
40:03
And the code that I used to do that, sorry, was just a little bit of a variation on what the gentleman on Stack Overflow had, which is let's take that expression of T that you're building, U goes to U.ID or U goes to U.Name,
40:24
and let's first try to coerce it as a member expression and then look at it as a unary expression. One of those should come back not null, and then we'll use the C sharp six feature, the null conditional operator, to just go ahead and try to drill into member, but if that is null, that will return a null,
40:43
and we'll use the null coalescing operator to say, okay, if that didn't work out, let's try to look at the unary expression and dig out the name of the member there. So, no if-else statements at least. As for interest, why have you got the second
41:01
of those question marks? This one? Yeah, is that necessary? Can we ever have a member expression that doesn't have a member? What was happening was if we, I believe this will blow up because, never mind.
41:22
I guess it depends on precedence of, yeah, at what point, and that's the one bit of the null coalescing operator, sorry, not null coalescing, null conditional operator that confuses me is, does it stop and apparently confuses Scott as to whether, when it reaches a null,
41:43
that's the end of that whole expression. It doesn't say, okay, I'll make that bit null and then try to keep going. So yeah, that's why it's okay with only the one of these. True. Yeah, I took a different approach that I didn't even bother writing the code for because it's so trivial.
42:01
I just used nameof. We want the name. Why would we bother creating an expression tree? And in fact, one of the bizarre things I think about the way that expression trees are done, this is a compiler implementation specific detail,
42:22
is every time you create an expression tree like that, I believe it creates a new expression tree. If you were using a lambda expression, if you had that with taking just a func T object, then the compiler could say, hey, I know that this u goes to u.name doesn't need anything from the enclosing,
42:45
any enclosing local variables, so hey, I'll just cache a delegate that can do that. Yeah, that's fine, and we can reuse the same delegate instance over and over again. But I don't think it does that for expression trees, which is bizarre because expression trees are immutable. And one of the nice things about immutability,
43:01
as you'll find out if you come to my talk this afternoon, is that we get to reuse objects and not care about things. So whether it was to avoid there being garbage collection things, I wouldn't have thought so. So yeah, having to create a new expression tree all the time for something that is fundamentally a compile-time constant,
43:22
the string name is a compile-time constant. So yeah, I would just use name, user.name. The other thing I would probably do is rather than, if I were using expression trees,
43:43
I would probably recurse rather than, I'd say if it's a unary expression, then take the body of that and just pump that into the same method again for a bit of fun. I think one of the reasons I immediately started thinking of expression trees,
44:02
it made me think of something very funny years ago. Rob, you probably remember the MVC contrib project. It was a library put together by the community to add things to ASP.NET MVC that weren't in the framework. And one of the contributors to that library, Jeremy Skinner, wrote an HTML helper to build a grid,
44:21
because every web application needs a grid. And he did it with a rather clever syntax. I enjoyed it. You could build a grid by saying I want an HTML.grid for this address that I have. Here are the columns. We'll show the city, the country, the street. Everything's strongly typed, so you don't have to specify anything as strings.
44:40
We're going to build the attributes on that table element to have a certain style and a certain ID and a certain border, so you can imagine it building out an HTML element that would say style equals width 100%, ID equals data, border equals one, blah, blah, blah, blah, blah. And just looking at the code, it seems very reasonable, it seems very readable.
45:00
And I thought, well, this is very pleasant. This is very pleasant. And then I saw this question on Stack Overflow that had two hysterical posts by Eric Lippert. Someone asked, is this an abuse of Lambda expressions? And why were they concerned? Because if you really think about it, how do we know?
45:23
Typically when you're setting HTML attributes from C-Sharp code, you have to do something with the string. You have to say I want to set the style attribute to width 100%. And there's a typo there, but that's okay. But notice what they're really doing. They're using an expression tree to analyze the name of a parameter,
45:43
which usually you only care about the name at compile time, right? And they're using that to generate something at run time. That's what would freak people out. In fact, Eric commented, this is hard in so many ways, and then later commented, I just asked Anders and the rest of the design team what they thought.
46:02
Let's just say the result would not be printable in a family-friendly newspaper. That's great. So this was 2009. I'm sure they would be working. So an alternative that I would have potentially used and would also probably be unprintable in terms of reactions,
46:20
would be why use a Lambda expression when if we could use dynamic typing, if columns returned dynamic, then you could call attributes and then style colon width 100%. And I think I've tripped you up on stage before now with dynamic link for let's just have a where clause
46:42
and say author colon and then the author name and whatever. And let's dig that out dynamically at execution time because, hey, it's all dynamic and pull that stuff. But, yeah, the more you can actually build it into compilation, the better. If you give a talk on C Sharp and John's in the audience, it's just not fun.
47:01
We were in NDC Oslo, and I was on stage. I was showing something I did with system.dynamic, and John said, if you were to just do this. And I'm like, oh, great. Why don't you just come up here and change my talk? But it was quite fun. It was quite fun. I didn't go up. I emailed Rob by the end of the talk instead. Yes. And I actually showed it on the screen. It actually worked. Yeah. Very good.
47:21
Actually, that was the genesis of Massive, my little project that I did. You inspired me on that. I wanted to go back to the question. Briefly, to say the problem with using nameOf, which is not actually a problem. There are some interesting, crazy corner cases with nameOf
47:42
around Unicode normalization and stuff. But in this case, nameOf would have worked because the questioner only wanted the name. The nice thing about expression trees, and I suspect is going to be used here in the columns, coms.for, is that you can then use the expression tree,
48:02
compile it down to a delegate, and actually execute the code. So if you need to get the city, country, and street, rather than just the text, city, country, street, then, yeah, expression trees is a perfectly reasonable way of doing things. Yes. Good point.
48:21
Is that it? Really? Yeah. You guys are French. Wow. I thought you would have more to say about that. I guess just use nameOf. Yeah. Use nameOf. All right. You caught me off guard then. Darn it. C sharp 6 just rocks. It certainly does. So many things. I have to say. Well, so we have this one last question about adding a dependency to a library.
48:40
You want to take that one? Yeah. So this is a no-code question, really. Well, I haven't got any code for it, anyway. But in fact, it's a question that has come up in my day job just in the last week or so. Oh, wow. So this is interesting. So you have a library that you are publishing on Nougat and things, and you want to add a new feature.
49:02
But adding a new feature, and it's not exactly the scenario here, but it's easier to explain. Adding a new feature means taking a new dependency. What do you do? You're following semantic versioning. What do you do with the version number? And this is one of those things where it really depends on what you mean by binary compatible.
49:22
And rather than arguing about angels dancing on the head of the pin, it's much more important to think, which scenarios would this break and which scenarios would it not break? So if you think of binary compatibility as what I'm going to do is install the package somewhere
49:42
and then manually copy and paste the DLL from A to B and then add a reference to that DLL, then this is a breaking change because you're copying that reference. You're not copying the extra library because all I'm doing is I'm just using a new compatible version of the library.
50:01
That's fine, right? And so in that sense, it's a breaking change. If, on the other hand, what you're interested in is with DNX or whatever doing a DNU restore, and it will update all the libraries, and you don't even need to recompile your code because it's binary compatibility we're talking about, then it's fine because DNU restore will have copied
50:22
the extra library and installed it, and all will be well. So it's really a matter of, for me, of scenarios, and of course the problem with open source code, I'm assuming this is an open source library, is you have no idea how people are using your code. So I would be slightly tempted,
50:41
well, I would probably first ask on my user's mailing list or whatever, how are people using this code? But then I would be tempted either to avoid the dependency if I could, as it sounds like the questioner could in this case because he's really refactoring it into a separate library,
51:01
or wait for the next major version, but... Yes. I'll be honest. I slightly misread the question at first, and I put together a little code sample based on that. It's quite possible that I did instead. No, no, no, no. I don't think you did. It was just sort of a long question, and I noticed it had a Java version,
51:20
and I had put together a code sample that I thought would maybe simulate a Java library, so I put together a little code sample with a iSingletonBean aspect-aware factory factory. That's when you need a factory to create the factory to create your Singleton beans that are aspect-aware. Shouldn't that derive from abstract Singleton Aspect-Aware factory factory?
51:43
That's quite possible, but I'll just tell you the end result of this. I just wanted to play around with this and do things like add additional methods to an interface, add additional classes, all of a sudden change the type of bean factory
52:00
that was returned from the factory factory, and the end result is I wasn't adding any new dependencies, like external dependencies and things like that. The beautiful thing about that interface, though, is I could change anything inside of here and not break binary compatibility, so I had a little thing where I was just building just the app
52:26
from the command line and running it and making sure that I got the same type of output and nothing broke, and there's really no way to break this until you do something like change the interface,
52:41
like change something that the client already had a dependency on, and of course then if I go out and I just save this file, I'm not going to build the library, build the application, I'm just going to build the library and run the application, and of course that's when I get an exception that, oh, we are still trying to call this create method that doesn't exist.
53:04
And the other interesting thing I thought about, talking about versioning, everyone loves semantic versioning, but there was a time when semantic versioning didn't exist, and you might know Donald Knuth, famous computer scientist,
53:23
wrote The Art of Computer Programming. He has a program called Text that he keeps updating. Notice the version number over here. I'm going to try to zoom in on that. I don't have my zooming capability. Does that number look somewhat familiar? So with every fix that he makes to Text now,
53:43
he adds another digit of pi to the version number. That's awesome. And the joke is that one day the program will be perfect and the version number will exactly match pi. I like it. Is it Text that's got a bug bounty program where the bounty doubles every time a bug is found?
54:02
Oh, I don't know. I think. And it's still only at sort of $1,024 or something crazy, and people never cash these checks. They frame them instead. If you have found a bug in Knuth's code, wow. Yeah. I have an interesting bit of compatibility that I'm just going to see if I can reproduce for fun.
54:25
So if you could talk about anything for two more minutes. Sure. I can keep rambling or we could take questions. I had a fun story about this, and I'm curious about what you would do. So I have a data access library I wrote for Elixir. And Elixir is a very young language, if you're not aware of. It's just written in the last few years.
54:42
But they keep adding things to it, and just recently they launched 1.2. Anyway, in my data access library I have a method called with. And it starts off a chain of events, and it worked great. And I liked the way it read. And so in version 1.2 of Elixir, they added the keyword with. Uh-oh. And so now people that use my stuff can't use Elixir 1.2,
55:03
which is a really strange position to be in, because if I remove that, now I've broken my API and I have to rev to 2.0. It's really a strange place to be. Anyway, there's my little story. Were you going to say something? I was. Sorry, yeah. Yeah, I don't remember, but I mean it is interesting how languages evolve.
55:21
And you can think about, when I was looking at the ECMAScript 2015 specification, just how careful you have to be about introducing new keywords to a language, because you don't know who you're going to break when you do that. And really C Sharp has that problem too now, right? When you want to introduce a new keyword like await, what about people that have variables declared
55:42
with the name await that can be a problem? I have a feeling Skeet would say, don't name a method. No, I think await has been designed so that it can't possibly be used The C Sharp team is incredibly sensitive to this. So it's a contextual keyword rather than a keyword.
56:03
And there are a few places, if you have a type called var or a type called dynamic, then you can have great fun with that. But then the contextual keyword will no longer mean that. And you can use where and select and from as identifiers elsewhere.
56:21
They're really smart about where this happens. Right, I think I'm probably ready to go. We can switch over to John, do you think? There's no guarantee that this is going to work, but it's based on an Eric Lippert blog post based on a Stack Overflow question from a while ago. We'll see what happens. So I have a library with a class called foo base
56:45
with a virtual method called var and a class called foo deriving from that that currently doesn't override var. I then have an app that has its own thing
57:03
that derives from foo, sorry. And that overrides var, but just calls base.var. So at the moment, if I run this program, we expect to see foo base.var, yes?
57:21
Because we're deriving from foo, which derives from foo base, and so base is going to call up and it stops when it hits foo base. Right, so if we run that, that shows foo base.var. If I uncomment this,
57:47
now logically the code would print foo.var, yeah? Because it's calling base.var and it's base class is foo. So this is from my foo.
58:02
The base class is foo, so it's calling base.var. It will call foo.var. And if I recompile everything, that will happen. But I think if I just build please only build the one thing. See, build one succeeded, yep. Right, I now need to go down to here
58:23
because if I do anything else, it will be too smart. So if I go into my compatibility app, bin debug, and so if I currently run this compatibility app, then it still shows foo base.var because I haven't recompiled anything yet.
58:43
The library and the app are both still at 955. If I copy over the new bin debug compatibility library.dll,
59:01
so we've still got the call to base.var. This is the new version. We should see a newer, yep, it's 956 instead. I believe it's still going to show foo base. Yes, foo base.var. And the reason for that is that a call to base,
59:22
base.var, doesn't say call my base class. It says call non-virtually what I at compile time know to be the most overridden version. So if we look in compatibility app.myfoo its.var method,
59:41
explicitly non-virtually calls foo base.var. So bizarrely, adding an override is sort of a bizarre breaking change because whether or not the behavior will change based on whether you recompile code that uses it or not,
01:00:01
which is quite surprising, I think. Yeah, we have two more minutes. So I thought it'd be cool if someone has a question, we could quickly answer it. Does anybody have a question? John's going to make you jump again. There's a lot of very silent people here. All right. Did you guys have anything else to add? I thought this was fun.
01:00:21
I did too. I had a good time. I get to randomly talk about things. It's always a good time. Thank you guys for coming. We had a really good time. And appreciate you guys showing up. Hope you enjoyed it. Thank you. Thank you.