WEBVTT

1
00:00:00.720 --> 00:00:04.679
<v Speaker 1>Imagine moving into a house where the walls like literally

2
00:00:04.719 --> 00:00:07.360
<v Speaker 1>shift and reorganize themselves depending on what kind of furniture

3
00:00:07.400 --> 00:00:08.400
<v Speaker 1>you decide to bring inside.

4
00:00:08.519 --> 00:00:10.560
<v Speaker 2>Right, just totally dynamic yea yeah, Like.

5
00:00:10.519 --> 00:00:12.720
<v Speaker 1>You bring in a tiny chair in the room shrinks

6
00:00:12.720 --> 00:00:15.119
<v Speaker 1>to hold it perfectly. You bring in a massive sofa,

7
00:00:15.359 --> 00:00:18.480
<v Speaker 1>the floor plan just completely rewires itself to accommodate it.

8
00:00:18.559 --> 00:00:21.600
<v Speaker 2>And a team of invisible workers just stands by to

9
00:00:21.640 --> 00:00:23.480
<v Speaker 2>haul it away the second you stop using it.

10
00:00:23.679 --> 00:00:28.000
<v Speaker 1>Exactly that dynamic, invisible architecture is basically the reality of

11
00:00:28.039 --> 00:00:31.839
<v Speaker 1>modern software. And today we are jumping into a deep

12
00:00:31.879 --> 00:00:34.640
<v Speaker 1>dive on the c sharp seven point zero pocket reference

13
00:00:34.960 --> 00:00:37.079
<v Speaker 1>by Joseph Albahari and Ben Albahari.

14
00:00:37.240 --> 00:00:39.679
<v Speaker 2>It's a fantastic resource, it really is.

15
00:00:39.840 --> 00:00:42.039
<v Speaker 1>We're going to figure out exactly how this language pulls

16
00:00:42.079 --> 00:00:47.159
<v Speaker 1>off this impossible high wire act. I mean, giving developers raw,

17
00:00:47.439 --> 00:00:51.920
<v Speaker 1>bare metal computational power without making them manage the messy,

18
00:00:52.200 --> 00:00:54.240
<v Speaker 1>unforgiving physics of computer memory.

19
00:00:54.320 --> 00:00:57.000
<v Speaker 2>It is a really delicate balance. Sea sharp is well.

20
00:00:57.039 --> 00:00:59.359
<v Speaker 2>It's a language built from the ground up to offer

21
00:00:59.399 --> 00:01:04.159
<v Speaker 2>the performance of older low level languages while simultaneously providing

22
00:01:04.200 --> 00:01:07.840
<v Speaker 2>an incredible safety net for your productivity. It's platform neutral,

23
00:01:07.879 --> 00:01:10.599
<v Speaker 2>so it runs practically anywhere, but it was really engineered

24
00:01:10.640 --> 00:01:13.920
<v Speaker 2>to sing when paired with the dot net framework. And

25
00:01:13.959 --> 00:01:17.120
<v Speaker 2>the text we're looking at today is this dense, insightful

26
00:01:17.200 --> 00:01:20.400
<v Speaker 2>roadmap of how that safety net actually functions under the hood.

27
00:01:20.920 --> 00:01:23.640
<v Speaker 1>And our mission for this deep dive isn't to just

28
00:01:24.200 --> 00:01:26.799
<v Speaker 1>read off syntax or build a glossar. No, that would

29
00:01:26.840 --> 00:01:30.840
<v Speaker 1>be boring totally. We want to understand the underlying DNA

30
00:01:31.079 --> 00:01:33.920
<v Speaker 1>of this system. How does it physically store your data,

31
00:01:34.439 --> 00:01:35.840
<v Speaker 1>what happens when that data.

32
00:01:35.640 --> 00:01:37.879
<v Speaker 2>Misbehaves or when it doesn't even exist right?

33
00:01:38.480 --> 00:01:42.920
<v Speaker 1>And how does it let developers express dizzyingly complex logic

34
00:01:43.159 --> 00:01:45.920
<v Speaker 1>without losing their minds. And I want to emphasize right

35
00:01:46.000 --> 00:01:48.920
<v Speaker 1>up front, even if you listening right now have never

36
00:01:48.959 --> 00:01:51.879
<v Speaker 1>written a single line of code in your life. Understanding

37
00:01:51.920 --> 00:01:55.599
<v Speaker 1>how a system like this organizes information, it can fundamentally

38
00:01:55.680 --> 00:01:58.799
<v Speaker 1>change how you approach problem solving. It just trains you

39
00:01:58.840 --> 00:02:00.400
<v Speaker 1>to think about structure.

40
00:02:00.239 --> 00:02:03.159
<v Speaker 2>And structure is exactly where we have to start, because

41
00:02:03.200 --> 00:02:06.159
<v Speaker 2>before you can manipulate data or build an application, you

42
00:02:06.200 --> 00:02:09.039
<v Speaker 2>have to understand how the system physically stores its foundation.

43
00:02:09.240 --> 00:02:11.479
<v Speaker 1>Okay, let's unpack this. We're talking about types.

44
00:02:11.240 --> 00:02:14.000
<v Speaker 2>Right, Yes, types. You can think of a type as

45
00:02:14.000 --> 00:02:17.159
<v Speaker 2>a blueprint for a value. The language comes with pre

46
00:02:17.199 --> 00:02:20.560
<v Speaker 2>defined types like an integer, which is just a whole number,

47
00:02:20.759 --> 00:02:24.159
<v Speaker 2>or a booleon which is a simple true or false switch.

48
00:02:24.360 --> 00:02:26.280
<v Speaker 1>But you can build your own too, Exactly, you.

49
00:02:26.199 --> 00:02:28.919
<v Speaker 2>Can build custom types like a unit converter or a

50
00:02:28.919 --> 00:02:33.520
<v Speaker 2>panda class, which basically bundle related data and behaviors together

51
00:02:33.599 --> 00:02:35.039
<v Speaker 2>into one neat package.

52
00:02:35.159 --> 00:02:38.599
<v Speaker 1>So we have our blueprints. But the authors highlight this

53
00:02:38.879 --> 00:02:42.439
<v Speaker 1>massive architectural divide and how c sharp actually builds those

54
00:02:42.439 --> 00:02:43.479
<v Speaker 1>blueprints in memory.

55
00:02:43.680 --> 00:02:46.039
<v Speaker 2>The value types versus reference types divide.

56
00:02:46.159 --> 00:02:49.280
<v Speaker 1>Yeah, and this basically dictates the entire physical reality of

57
00:02:49.280 --> 00:02:49.919
<v Speaker 1>the program.

58
00:02:50.000 --> 00:02:54.159
<v Speaker 2>It is arguably the single most critical distinction in the language,

59
00:02:54.319 --> 00:02:56.879
<v Speaker 2>and it comes down to two very different physical locations

60
00:02:56.879 --> 00:02:59.319
<v Speaker 2>in your computer's memory, the stack and the heap.

61
00:02:59.439 --> 00:03:00.319
<v Speaker 1>The stack in the heap.

62
00:03:00.400 --> 00:03:03.639
<v Speaker 2>Right, value types live on the stack. Reference types live

63
00:03:03.680 --> 00:03:06.599
<v Speaker 2>on the heap. The text uses a custom type called point,

64
00:03:06.639 --> 00:03:09.159
<v Speaker 2>representing an X and y coordinate on a graph to

65
00:03:09.199 --> 00:03:09.840
<v Speaker 2>demonstrate this.

66
00:03:10.000 --> 00:03:11.199
<v Speaker 1>Okay, so how does that work.

67
00:03:11.360 --> 00:03:14.000
<v Speaker 2>Well, if you define your point blueprint as a struct

68
00:03:14.560 --> 00:03:17.840
<v Speaker 2>the language treats it as a value type. When you

69
00:03:17.879 --> 00:03:21.280
<v Speaker 2>create a variable called P one. The actual X and

70
00:03:21.439 --> 00:03:24.800
<v Speaker 2>Y numbers are physically stuffed right inside P one on

71
00:03:24.840 --> 00:03:25.240
<v Speaker 2>the stack.

72
00:03:25.360 --> 00:03:25.840
<v Speaker 1>Oh wow.

73
00:03:26.080 --> 00:03:27.719
<v Speaker 2>And if you then write a line of code that

74
00:03:27.719 --> 00:03:31.840
<v Speaker 2>says P two equals P one, the system physically duplicates

75
00:03:31.879 --> 00:03:35.240
<v Speaker 2>those numbers. It carves out a brand new independent chunk

76
00:03:35.280 --> 00:03:36.360
<v Speaker 2>of memory for P two.

77
00:03:36.599 --> 00:03:39.400
<v Speaker 1>Right, So I've then changed P one's ex coordinate to

78
00:03:39.400 --> 00:03:43.120
<v Speaker 1>be the number nine. P two's ex coordinate stays exactly.

79
00:03:42.680 --> 00:03:43.879
<v Speaker 2>What it was precisely.

80
00:03:43.960 --> 00:03:47.280
<v Speaker 1>They're completely isolated. It's like, okay, It's like having a

81
00:03:47.360 --> 00:03:50.120
<v Speaker 1>super secret chocolate chip cookie recipe written on a piece

82
00:03:50.159 --> 00:03:52.280
<v Speaker 1>of paper and I hand you a photocopy of it.

83
00:03:52.360 --> 00:03:53.199
<v Speaker 2>I like that analogy.

84
00:03:53.280 --> 00:03:55.520
<v Speaker 1>You can take a sharpie, cross out the chocolate chips

85
00:03:55.520 --> 00:03:57.439
<v Speaker 1>and write in raisins, which, by the way, would be

86
00:03:57.479 --> 00:04:00.520
<v Speaker 1>a total crime against baking. But my original recipe is

87
00:04:00.560 --> 00:04:02.800
<v Speaker 1>totally safe. You're Edits don't affect my paper.

88
00:04:02.919 --> 00:04:05.560
<v Speaker 2>What's fascinating here is that the beauty of that photocopy

89
00:04:05.599 --> 00:04:08.560
<v Speaker 2>approach is the system doesn't have to manage it long term.

90
00:04:08.960 --> 00:04:12.319
<v Speaker 2>Once the function you're running finishes, your photocopy is just

91
00:04:12.360 --> 00:04:12.840
<v Speaker 2>thrown in.

92
00:04:12.759 --> 00:04:14.120
<v Speaker 1>The trash, just tossed out.

93
00:04:14.400 --> 00:04:17.560
<v Speaker 2>Yeah, that is the nature of the stack. It operates

94
00:04:17.639 --> 00:04:21.800
<v Speaker 2>like a literal stack of cafeteria trays. Variables are piled

95
00:04:21.839 --> 00:04:23.759
<v Speaker 2>on top of each other as they are needed, and

96
00:04:23.800 --> 00:04:25.959
<v Speaker 2>as soon as a task is done, the top crazer

97
00:04:26.120 --> 00:04:29.639
<v Speaker 2>just popped off and instantly destroyed. So fast, lightning fast.

98
00:04:29.920 --> 00:04:32.800
<v Speaker 2>But it is strictly scoped and small. You can't put

99
00:04:32.800 --> 00:04:34.279
<v Speaker 2>everything on the stack, which.

100
00:04:34.079 --> 00:04:36.600
<v Speaker 1>Brings us to the other side of the divide, the heap.

101
00:04:37.079 --> 00:04:39.439
<v Speaker 1>What if we take that exact same point code, but

102
00:04:39.519 --> 00:04:42.439
<v Speaker 1>we change the blueprint from a struct to a class.

103
00:04:42.600 --> 00:04:45.600
<v Speaker 2>A class creates a reference type. Now when you create

104
00:04:45.680 --> 00:04:48.439
<v Speaker 2>P one, the actual heavy data that X and y

105
00:04:48.560 --> 00:04:51.439
<v Speaker 2>coordinates is created over in the heat, and the heap

106
00:04:51.519 --> 00:04:56.199
<v Speaker 2>is like it's like a sprawling, unstructured warehouse for complex

107
00:04:56.279 --> 00:04:58.279
<v Speaker 2>objects that need to live for a long time. The

108
00:04:58.360 --> 00:05:02.000
<v Speaker 2>variable P one sitting on the doesn't hold the numbers anymore.

109
00:05:02.360 --> 00:05:05.240
<v Speaker 2>It just holds a pointer, like a reference, telling the

110
00:05:05.240 --> 00:05:07.480
<v Speaker 2>computer where to find the data in the warehouse.

111
00:05:07.720 --> 00:05:11.240
<v Speaker 1>So, following my analogy, a reference type isn't a photocopy.

112
00:05:11.240 --> 00:05:13.160
<v Speaker 1>It's like I shared the link to a live Google

113
00:05:13.199 --> 00:05:15.399
<v Speaker 1>doc with you. We are both looking at the exact

114
00:05:15.439 --> 00:05:16.079
<v Speaker 1>same document.

115
00:05:16.240 --> 00:05:18.720
<v Speaker 2>Yes, and if you say P two equals P one.

116
00:05:18.800 --> 00:05:21.279
<v Speaker 2>Now the system doesn't copy the data, it just copies

117
00:05:21.279 --> 00:05:24.519
<v Speaker 2>the link. Oh wow, both variables point to the exact

118
00:05:24.519 --> 00:05:28.279
<v Speaker 2>same object in the warehouse. If you change P one's

119
00:05:28.399 --> 00:05:31.199
<v Speaker 2>ex coordinate to nine and then ask the computer what

120
00:05:31.319 --> 00:05:34.079
<v Speaker 2>P two's ex coordinate is, it will also be nine.

121
00:05:34.399 --> 00:05:35.879
<v Speaker 2>They are intrinsically linked.

122
00:05:36.160 --> 00:05:38.399
<v Speaker 1>But wait, if the stack just throws away its trays

123
00:05:38.439 --> 00:05:41.040
<v Speaker 1>when it's done, what happens to all the heavy data

124
00:05:41.079 --> 00:05:44.000
<v Speaker 1>sitting out in the heap warehouse? Doesn't it just pile up?

125
00:05:44.120 --> 00:05:47.120
<v Speaker 2>That is where c Sharp's invisible workers come in. The

126
00:05:47.199 --> 00:05:50.680
<v Speaker 2>heap requires a cleanup crew known as the garbage collector.

127
00:05:50.360 --> 00:05:52.040
<v Speaker 1>The famous garbage collector.

128
00:05:51.839 --> 00:05:55.120
<v Speaker 2>Exactly, It constantly runs in the background tracing all the

129
00:05:55.120 --> 00:05:57.879
<v Speaker 2>active links from the stack into the keep. The moment

130
00:05:57.920 --> 00:06:00.240
<v Speaker 2>it realizes that a piece of data in the warehouse

131
00:06:00.279 --> 00:06:03.519
<v Speaker 2>has absolutely no links pointing to it anymore, meaning no

132
00:06:03.639 --> 00:06:06.360
<v Speaker 2>part of your program can even reach it, the garbage

133
00:06:06.399 --> 00:06:10.519
<v Speaker 2>collector sweeps it up and frees the memory. That's incredibly convenient,

134
00:06:10.680 --> 00:06:14.120
<v Speaker 2>it is you get the raw power of complex, long

135
00:06:14.160 --> 00:06:17.160
<v Speaker 2>lived objects without having to manually command the computer to

136
00:06:17.199 --> 00:06:20.439
<v Speaker 2>delete them, which honestly was a massive source of bugs

137
00:06:20.480 --> 00:06:21.439
<v Speaker 2>in older languages.

138
00:06:21.639 --> 00:06:25.439
<v Speaker 1>So we've mapped out how C sharp physically stores its foundation,

139
00:06:26.000 --> 00:06:29.560
<v Speaker 1>balancing the fast stack with the garbage collected heap. But

140
00:06:29.639 --> 00:06:32.879
<v Speaker 1>a pile of data isn't always perfectly well behaved.

141
00:06:32.920 --> 00:06:33.600
<v Speaker 2>It's not at all.

142
00:06:33.720 --> 00:06:36.319
<v Speaker 1>Let's look at what happens when the actual information inside

143
00:06:36.319 --> 00:06:39.319
<v Speaker 1>these structures gets weird. I was reading the section on

144
00:06:39.399 --> 00:06:42.639
<v Speaker 1>numeric types, and the text gives this mathematical example that

145
00:06:42.839 --> 00:06:46.079
<v Speaker 1>completely broke my brain for a second. Floating point math.

146
00:06:46.480 --> 00:06:50.399
<v Speaker 2>Ah, Yes, the infamous divide between the double type and

147
00:06:50.439 --> 00:06:53.600
<v Speaker 2>the decimal type. It traps developers constantly.

148
00:06:53.720 --> 00:06:56.480
<v Speaker 1>It's wild. The authors show this specific equation. You take

149
00:06:56.560 --> 00:06:59.480
<v Speaker 1>zero point one multiplied by ten, which is exactly one

150
00:07:00.199 --> 00:07:04.079
<v Speaker 1>track that result from one one mius one. The answer

151
00:07:04.199 --> 00:07:05.279
<v Speaker 1>universally should.

152
00:07:05.000 --> 00:07:06.399
<v Speaker 2>Be zero, right basic math.

153
00:07:06.560 --> 00:07:09.040
<v Speaker 1>But in C sharp, if you use the standard double

154
00:07:09.040 --> 00:07:11.480
<v Speaker 1>type for this, the answer it spits out is negative

155
00:07:11.519 --> 00:07:13.319
<v Speaker 1>one point four to nine, followed by an e in

156
00:07:13.319 --> 00:07:17.279
<v Speaker 1>andh eight. It's this microscopic, weird negative fraction. Why does

157
00:07:17.319 --> 00:07:20.519
<v Speaker 1>a basic subtraction equation completely fail to equal zero?

158
00:07:20.759 --> 00:07:23.920
<v Speaker 2>It's entirely about how the physical processor of your computer

159
00:07:24.040 --> 00:07:27.720
<v Speaker 2>understands fractions. The double type represents numbers in base two,

160
00:07:28.120 --> 00:07:31.639
<v Speaker 2>it uses binary. Now think about our human base ten system.

161
00:07:32.319 --> 00:07:35.439
<v Speaker 2>You cannot perfectly represent the fraction one third in base ten.

162
00:07:35.600 --> 00:07:37.800
<v Speaker 2>It becomes zero point three to three to three, repeating

163
00:07:37.800 --> 00:07:40.279
<v Speaker 2>into infinity. You have to chop it off eventually. Right,

164
00:07:40.759 --> 00:07:43.040
<v Speaker 2>The exact same thing happens to the computer in base

165
00:07:43.040 --> 00:07:45.839
<v Speaker 2>two binary when it tries to represent the fraction zero

166
00:07:45.920 --> 00:07:49.439
<v Speaker 2>point one. It can't do it cleanly. It becomes a repeating,

167
00:07:49.560 --> 00:07:51.480
<v Speaker 2>imprecise binary fraction.

168
00:07:51.639 --> 00:07:54.000
<v Speaker 1>Oh so it's chopping off the end of the binary decimal,

169
00:07:54.360 --> 00:07:57.560
<v Speaker 1>and when you do math with it, those microscopic chopped

170
00:07:57.560 --> 00:08:01.040
<v Speaker 1>off in precisions compound, leaving you with that weird negative

171
00:08:01.040 --> 00:08:02.720
<v Speaker 1>exponential instead of a clean zero.

172
00:08:02.920 --> 00:08:07.199
<v Speaker 2>Precisely, the double type sacrifices absolute precision to fit into

173
00:08:07.240 --> 00:08:07.920
<v Speaker 2>a base two.

174
00:08:07.879 --> 00:08:11.399
<v Speaker 1>Format, which means if I am writing, say, banking software,

175
00:08:11.480 --> 00:08:14.720
<v Speaker 1>and I use double to calculate dally interest rates, over

176
00:08:14.759 --> 00:08:17.079
<v Speaker 1>a few years, I'm going to be losing or inventing

177
00:08:17.120 --> 00:08:18.560
<v Speaker 1>fractions of panties everywhere.

178
00:08:18.639 --> 00:08:21.680
<v Speaker 2>The accounting department would audit you into oblivion exactly. So

179
00:08:21.680 --> 00:08:25.040
<v Speaker 2>how do we fix it for financial calculations? The text

180
00:08:25.079 --> 00:08:28.480
<v Speaker 2>emphasizes you must use the decimal type. The decimal type

181
00:08:28.519 --> 00:08:30.879
<v Speaker 2>operates in base ten. It stores the number as a

182
00:08:30.920 --> 00:08:34.039
<v Speaker 2>massive integer and just remembers exactly where the decimal point goes.

183
00:08:34.399 --> 00:08:35.600
<v Speaker 2>So it's super precise.

184
00:08:35.840 --> 00:08:38.840
<v Speaker 1>Very it has twenty eight to twenty nine significant figures

185
00:08:38.840 --> 00:08:42.480
<v Speaker 1>of absolute precision. Zero point one is stored perfectly a

186
00:08:42.600 --> 00:08:43.200
<v Speaker 1>zero point one.

187
00:08:43.240 --> 00:08:46.360
<v Speaker 2>Wait a second. If decimal gives us perfect human math

188
00:08:46.440 --> 00:08:49.600
<v Speaker 2>without the compounding rounding errors, why do we even keep

189
00:08:49.639 --> 00:08:52.440
<v Speaker 2>double around. Aren't we just asking for accounting bugs by

190
00:08:52.519 --> 00:08:55.360
<v Speaker 2>leaving an imprecise math type in the language. Why not

191
00:08:55.480 --> 00:08:57.399
<v Speaker 2>just use decimal for absolutely everything?

192
00:08:57.759 --> 00:09:00.440
<v Speaker 1>If we connect this to the bigger picture, it's because

193
00:09:00.440 --> 00:09:03.960
<v Speaker 1>of the raw hardware physics. Your computer's processor has a

194
00:09:03.960 --> 00:09:07.399
<v Speaker 1>dedicated floating point unit physically wired to crunch base two

195
00:09:07.519 --> 00:09:09.080
<v Speaker 1>numbers at blinding speed.

196
00:09:09.240 --> 00:09:11.120
<v Speaker 2>Oh so with the speed thing exactly.

197
00:09:11.440 --> 00:09:14.120
<v Speaker 1>The double type runs natively on that hardware. That decimal

198
00:09:14.159 --> 00:09:17.320
<v Speaker 1>type is non native. It's a software construct. The processor

199
00:09:17.320 --> 00:09:19.799
<v Speaker 1>has to do a massive amount of extra simulated work

200
00:09:19.799 --> 00:09:23.320
<v Speaker 1>to process base ten math. Because of that physical reality,

201
00:09:23.519 --> 00:09:26.919
<v Speaker 1>double is roughly ten times faster to compute than decimal. Okay,

202
00:09:26.960 --> 00:09:29.720
<v Speaker 1>that makes perfect sense. If I'm programming a three D

203
00:09:29.799 --> 00:09:33.799
<v Speaker 1>physics engine and calculating the spatial coordinates of fifty thousand

204
00:09:33.879 --> 00:09:37.200
<v Speaker 1>colliding particles sixty times a second. I really don't care

205
00:09:37.200 --> 00:09:39.440
<v Speaker 1>if a particle's position is off by a billionth of

206
00:09:39.480 --> 00:09:42.639
<v Speaker 1>a millimeter. I just needed to render instantly exactly.

207
00:09:43.080 --> 00:09:46.840
<v Speaker 2>Double is for science graphics, and raw speed decimal is

208
00:09:46.840 --> 00:09:51.120
<v Speaker 2>for human made values like currency, where precision is non negotiable.

209
00:09:51.519 --> 00:09:54.799
<v Speaker 1>So that's the quirk of imprecise data. But what about

210
00:09:54.799 --> 00:09:58.360
<v Speaker 1>when data just doesn't exist at all? The concept of.

211
00:09:58.360 --> 00:09:59.840
<v Speaker 2>Null, that's a huge one.

212
00:10:00.000 --> 00:10:02.879
<v Speaker 1>The book explains that value types the photocopies on the

213
00:10:02.879 --> 00:10:06.159
<v Speaker 1>sack can't ordinarily be null. They have to hold a value,

214
00:10:06.320 --> 00:10:09.799
<v Speaker 1>even if it's just a zero. But reference types, those

215
00:10:09.840 --> 00:10:12.759
<v Speaker 1>links to the Google doc can absolutely be null, meaning

216
00:10:12.840 --> 00:10:14.440
<v Speaker 1>the pointer is pointing at empty.

217
00:10:14.159 --> 00:10:17.200
<v Speaker 2>Space, and this leads to the infamous null reference exception.

218
00:10:17.320 --> 00:10:20.759
<v Speaker 2>To a developer, those three words are terrifying. It is

219
00:10:20.879 --> 00:10:23.279
<v Speaker 2>arguably the most common way software crashes.

220
00:10:23.600 --> 00:10:26.039
<v Speaker 1>Let's visualize the mechanism of that crash for a second.

221
00:10:26.679 --> 00:10:29.840
<v Speaker 1>To a non programmer, why does a pointer pointing to

222
00:10:29.919 --> 00:10:33.840
<v Speaker 1>nothing cause the whole system to explode? It's like if

223
00:10:33.879 --> 00:10:35.919
<v Speaker 1>you tell the computer to go read the Google doc

224
00:10:36.399 --> 00:10:39.039
<v Speaker 1>and it follows the link only to find an empty void.

225
00:10:39.720 --> 00:10:41.000
<v Speaker 1>It just panics, right.

226
00:10:41.000 --> 00:10:42.399
<v Speaker 2>It doesn't know what to do next, so.

227
00:10:42.360 --> 00:10:44.360
<v Speaker 1>The program simply drops dead.

228
00:10:44.639 --> 00:10:47.639
<v Speaker 2>That panic is exactly what happens. This system attempts an

229
00:10:47.679 --> 00:10:50.519
<v Speaker 2>operation on memory that doesn't exist, and the only safe

230
00:10:50.519 --> 00:10:54.320
<v Speaker 2>response is to halt execution entirely. But to combat this,

231
00:10:54.799 --> 00:10:59.360
<v Speaker 2>c Sharp introduced incredibly elegant syntax to safely check for

232
00:10:59.399 --> 00:11:00.799
<v Speaker 2>that void with without crashing.

233
00:11:00.879 --> 00:11:04.360
<v Speaker 1>The null conditional operator, or, as it's affectionately known, the

234
00:11:04.360 --> 00:11:05.679
<v Speaker 1>Elvis operator.

235
00:11:05.279 --> 00:11:07.559
<v Speaker 2>Yes because the question mark and the dot next to

236
00:11:07.600 --> 00:11:10.759
<v Speaker 2>each other looks slightly like Elvis Presley's swooping hair in

237
00:11:10.799 --> 00:11:11.240
<v Speaker 2>an eye.

238
00:11:11.320 --> 00:11:13.919
<v Speaker 1>I know, you literally can't unsee it once you notice it,

239
00:11:14.639 --> 00:11:18.679
<v Speaker 1>But functionally, how does elvis save the program from panicking.

240
00:11:19.000 --> 00:11:20.840
<v Speaker 2>Let's say you want to extract a text string from

241
00:11:20.840 --> 00:11:23.080
<v Speaker 2>a variable, so you write the command to get that string.

242
00:11:23.120 --> 00:11:25.960
<v Speaker 2>If the variable is null, boom, the program crashes. But

243
00:11:26.200 --> 00:11:29.240
<v Speaker 2>if you insert the Elvis operator the question mark and

244
00:11:29.320 --> 00:11:32.559
<v Speaker 2>the dot right before the command, it short circuits the panic.

245
00:11:33.120 --> 00:11:36.279
<v Speaker 2>It essentially whispers to the compiler, hey, if this variable

246
00:11:36.320 --> 00:11:39.200
<v Speaker 2>happens to be a void, just stop right here. Don't

247
00:11:39.240 --> 00:11:41.600
<v Speaker 2>even try to read the text, just hand me back

248
00:11:41.600 --> 00:11:43.559
<v Speaker 2>a null and let's quietly move.

249
00:11:43.399 --> 00:11:46.440
<v Speaker 1>On, no crash, and you can seamlessly pair it with

250
00:11:46.480 --> 00:11:49.840
<v Speaker 1>another tool. Right. Yeah, the null coalescing operator, which is

251
00:11:50.000 --> 00:11:52.120
<v Speaker 1>just two question marks in a row exactly.

252
00:11:52.159 --> 00:11:54.080
<v Speaker 2>It acts like a backup generator.

253
00:11:53.879 --> 00:11:55.679
<v Speaker 1>So you try to read the text with Elvis and

254
00:11:55.720 --> 00:11:58.360
<v Speaker 1>then use the two question marks to say if you

255
00:11:58.440 --> 00:12:01.840
<v Speaker 1>hit a void, just substance too the word unknown instead.

256
00:12:02.519 --> 00:12:05.799
<v Speaker 1>It condenses what used to be a clunky multiline error

257
00:12:05.840 --> 00:12:09.360
<v Speaker 1>checking routine into one sleek, panic free line of code.

258
00:12:09.440 --> 00:12:12.360
<v Speaker 2>It removes the friction of defensive programming, and C sharp

259
00:12:12.399 --> 00:12:15.679
<v Speaker 2>seven took that friction removal further with tuples, which solved

260
00:12:15.679 --> 00:12:17.600
<v Speaker 2>the opposite problem returning too much data.

261
00:12:17.720 --> 00:12:21.000
<v Speaker 1>Oh tuples right. Historically, if a single function needed to

262
00:12:21.039 --> 00:12:23.919
<v Speaker 1>calculate and hand back two distinct things, say a person's

263
00:12:24.000 --> 00:12:27.039
<v Speaker 1>name and their age, you had to jump through ridiculous hoops.

264
00:12:27.159 --> 00:12:28.639
<v Speaker 2>It was a meth You either had to.

265
00:12:28.559 --> 00:12:32.519
<v Speaker 1>Build a completely separate, dummy blueprint class just to hold

266
00:12:32.519 --> 00:12:35.080
<v Speaker 1>those two variables together, or you had to use these

267
00:12:35.159 --> 00:12:39.200
<v Speaker 1>clunky out parameters that made the code super difficult to read.

268
00:12:39.440 --> 00:12:42.360
<v Speaker 2>Tuples bypass all of that. Backed by a lightweight value

269
00:12:42.360 --> 00:12:45.679
<v Speaker 2>type called value tuple. They let you elegantly bundle values

270
00:12:45.720 --> 00:12:48.519
<v Speaker 2>together on the fly. You literally just put the name

271
00:12:48.559 --> 00:12:52.120
<v Speaker 2>Bob and his age twenty three in parentheses and assign

272
00:12:52.120 --> 00:12:56.840
<v Speaker 2>it to a variable. The compiler handles the underlying structure automatically, and.

273
00:12:56.799 --> 00:12:59.480
<v Speaker 1>The deconstruction syntax is even better. You can call that

274
00:12:59.519 --> 00:13:03.759
<v Speaker 1>function instantly split the tupple back into individual usable variable. Yes,

275
00:13:03.759 --> 00:13:06.600
<v Speaker 1>the deconstructor you just write parentheses the word string and

276
00:13:06.679 --> 00:13:08.840
<v Speaker 1>the variable name, followed by the word end in the

277
00:13:08.879 --> 00:13:12.240
<v Speaker 1>variable age. Boom, you have two local variables ready to

278
00:13:12.279 --> 00:13:15.200
<v Speaker 1>go without ever defining a custom class. It keeps the

279
00:13:15.240 --> 00:13:16.639
<v Speaker 1>works based incredibly clean.

280
00:13:16.759 --> 00:13:20.600
<v Speaker 2>So we have our structural foundation. We've navigated the mathematical quirks,

281
00:13:20.879 --> 00:13:24.240
<v Speaker 2>and we've tamed the voids with graceful operators. But a

282
00:13:24.279 --> 00:13:27.679
<v Speaker 2>program isn't just a static warehouse of data. We need action.

283
00:13:28.240 --> 00:13:31.240
<v Speaker 1>We need logic which moves us right into how c

284
00:13:31.440 --> 00:13:34.120
<v Speaker 1>sharp passes behaviors around. We know how to put the

285
00:13:34.200 --> 00:13:36.759
<v Speaker 1>number five into a variable, but how do we put

286
00:13:36.759 --> 00:13:40.320
<v Speaker 1>an actual action like a math calculation into a variable.

287
00:13:40.399 --> 00:13:43.960
<v Speaker 2>That is the domain of delegates. A delegate is fundamentally

288
00:13:44.000 --> 00:13:46.799
<v Speaker 2>a type that represents a reference to a method. Think

289
00:13:46.840 --> 00:13:48.480
<v Speaker 2>of it as a pluggable protocol.

290
00:13:48.720 --> 00:13:50.200
<v Speaker 1>Yeah, a protocol, right.

291
00:13:50.519 --> 00:13:53.519
<v Speaker 2>It defines exactly what a method's inputs and outputs should

292
00:13:53.519 --> 00:13:56.679
<v Speaker 2>look like. The authors use a transformer delegate as an example.

293
00:13:57.159 --> 00:14:00.000
<v Speaker 2>If you define a protocol that takes an integer, all

294
00:14:00.000 --> 00:14:03.039
<v Speaker 2>alters it, and returns an integer, you can assign any

295
00:14:03.120 --> 00:14:06.360
<v Speaker 2>actual method that matches that fingerprint to a delegate variable.

296
00:14:06.679 --> 00:14:09.080
<v Speaker 1>So what does this all mean? The immediate question for

297
00:14:09.080 --> 00:14:11.799
<v Speaker 1>anyone looking at this is why not just call the

298
00:14:11.840 --> 00:14:15.000
<v Speaker 1>method directly? Why bother creating a middleman?

299
00:14:15.440 --> 00:14:19.159
<v Speaker 2>Because the middleman allows for brilliant decoupling. If you write

300
00:14:19.200 --> 00:14:21.600
<v Speaker 2>a generic engine that loops through a massive list of

301
00:14:21.720 --> 00:14:25.440
<v Speaker 2>numbers and applies some transformation to each one, that engine

302
00:14:25.480 --> 00:14:28.559
<v Speaker 2>shouldn't need to know what the transformation actually is. Oh,

303
00:14:28.559 --> 00:14:30.320
<v Speaker 2>it just does the work, right, It just needs a

304
00:14:30.360 --> 00:14:33.679
<v Speaker 2>delegate at runtime. You can plug in a method that

305
00:14:33.720 --> 00:14:37.399
<v Speaker 2>squares the numbers, or a completely different method that has them.

306
00:14:37.919 --> 00:14:41.080
<v Speaker 2>The delegate makes your architecture modular.

307
00:14:41.000 --> 00:14:43.919
<v Speaker 1>And the language evolved a wonderfully concise way to write

308
00:14:43.960 --> 00:14:46.080
<v Speaker 1>those plug in methods lambda expressions.

309
00:14:46.120 --> 00:14:47.279
<v Speaker 2>They are everywhere now.

310
00:14:47.399 --> 00:14:50.399
<v Speaker 1>Instead of writing out a whole separate named method just

311
00:14:50.399 --> 00:14:53.320
<v Speaker 1>to square number, you write it in line. You literally

312
00:14:53.360 --> 00:14:55.879
<v Speaker 1>just write the variable say x an arrow and then

313
00:14:56.039 --> 00:14:56.799
<v Speaker 1>x times x.

314
00:14:57.000 --> 00:14:59.320
<v Speaker 2>The compiler reads the arrow as goes.

315
00:14:59.039 --> 00:15:04.240
<v Speaker 1>To baraily minimalist. But this minimalism hides what I found

316
00:15:04.240 --> 00:15:06.519
<v Speaker 1>to be the most fascinating trap in the entire book,

317
00:15:07.639 --> 00:15:08.519
<v Speaker 1>the closure trap.

318
00:15:08.759 --> 00:15:12.519
<v Speaker 2>Oh yes, this is a spectacular aha moment for understanding

319
00:15:12.559 --> 00:15:13.759
<v Speaker 2>compiler architecture.

320
00:15:13.919 --> 00:15:16.080
<v Speaker 1>Let's lay out the scenario from the text. We build

321
00:15:16.080 --> 00:15:18.960
<v Speaker 1>a simple four loop. The loop uses an integer variable

322
00:15:18.960 --> 00:15:21.559
<v Speaker 1>eye that starts at zero, goes to one, then goes

323
00:15:21.600 --> 00:15:25.159
<v Speaker 1>to two, and finishes a standard loop right and inside

324
00:15:25.240 --> 00:15:28.200
<v Speaker 1>that loop, we create a tiny lamba expression that just

325
00:15:28.320 --> 00:15:31.399
<v Speaker 1>prints the value of ee. We stash those three lambdas

326
00:15:31.399 --> 00:15:34.840
<v Speaker 1>in a array to be executed later on. Common sense

327
00:15:34.879 --> 00:15:37.440
<v Speaker 1>dictates that the first lamb to capture the zero, the

328
00:15:37.480 --> 00:15:39.679
<v Speaker 1>second capture of the one, and the third capture of

329
00:15:39.679 --> 00:15:41.440
<v Speaker 1>the two. That's what you would expect, So when we

330
00:15:41.480 --> 00:15:45.120
<v Speaker 1>run them later, they should print zero, one, two, But

331
00:15:45.200 --> 00:15:47.799
<v Speaker 1>they don't. When you run them, they print three, three three.

332
00:15:48.279 --> 00:15:50.200
<v Speaker 1>Why is the computer ignoring the past?

333
00:15:51.000 --> 00:15:53.960
<v Speaker 2>Because of the physical reality of what a lamba actually captures.

334
00:15:54.159 --> 00:15:56.200
<v Speaker 2>It doesn't take a snapshot of the value of the

335
00:15:56.279 --> 00:15:59.360
<v Speaker 2>variable at the exact millisecond. The lambda is created.

336
00:15:59.519 --> 00:16:00.519
<v Speaker 1>Wait it doesn't.

337
00:16:00.600 --> 00:16:03.519
<v Speaker 2>No, it captures a reference to the variable itself. It

338
00:16:03.600 --> 00:16:06.399
<v Speaker 2>locks onto the memory location. By the time the four

339
00:16:06.440 --> 00:16:10.120
<v Speaker 2>loop finishes spinning, that single shared variable Eye has been

340
00:16:10.159 --> 00:16:11.279
<v Speaker 2>incremented up to three.

341
00:16:11.879 --> 00:16:12.639
<v Speaker 1>Oh wow.

342
00:16:12.720 --> 00:16:15.919
<v Speaker 2>So later, when those three lamb does finally wake up

343
00:16:15.919 --> 00:16:18.840
<v Speaker 2>and execute, they all look at that single shared memory

344
00:16:18.879 --> 00:16:21.039
<v Speaker 2>location and they all see the number three.

345
00:16:21.480 --> 00:16:23.399
<v Speaker 1>The book points out, the fix is to create a

346
00:16:23.440 --> 00:16:26.759
<v Speaker 1>brand new local variable inside the loops brackets, copy the

347
00:16:26.799 --> 00:16:28.799
<v Speaker 1>value of eye into it, and have the lamb to

348
00:16:28.879 --> 00:16:31.240
<v Speaker 1>capture that new inner variable exactly.

349
00:16:31.559 --> 00:16:34.559
<v Speaker 2>Since a brand new physical variable is created on the stack,

350
00:16:34.600 --> 00:16:37.600
<v Speaker 2>for every single spin of the loop, each lambda gets

351
00:16:37.600 --> 00:16:40.960
<v Speaker 2>its own isolated box to look at. That establishes true

352
00:16:41.000 --> 00:16:42.399
<v Speaker 2>isolation for each closure.

353
00:16:42.480 --> 00:16:44.480
<v Speaker 1>Well, wait, I have to puzzle through the physics of this.

354
00:16:45.399 --> 00:16:48.840
<v Speaker 1>If a lambda captures an outer variable and we stash

355
00:16:48.919 --> 00:16:51.879
<v Speaker 1>that lambda away to be run ten minutes later, doesn't

356
00:16:51.879 --> 00:16:53.960
<v Speaker 1>that artificially extend the life of that variable.

357
00:16:54.120 --> 00:16:54.879
<v Speaker 2>Yes, it does.

358
00:16:55.039 --> 00:16:58.639
<v Speaker 1>Like our loop variable was a value type on the stack,

359
00:16:58.879 --> 00:17:01.000
<v Speaker 1>it was supposed to be thrown in the trash the

360
00:17:01.039 --> 00:17:04.039
<v Speaker 1>millisecond the loop finished. If the lamb is still referencing

361
00:17:04.079 --> 00:17:07.359
<v Speaker 1>it ten minutes later, how does it survive? Isn't this

362
00:17:07.440 --> 00:17:09.799
<v Speaker 1>just a massive memory leak waiting to happen?

363
00:17:10.079 --> 00:17:12.759
<v Speaker 2>This raises an important question, and your intuition is pointing

364
00:17:12.799 --> 00:17:16.440
<v Speaker 2>directly at the compiler's most complex magic trick. How does

365
00:17:16.440 --> 00:17:19.920
<v Speaker 2>a short lived stack variable survive? It survives because the

366
00:17:19.920 --> 00:17:24.000
<v Speaker 2>compiler secretly rewrites your code behind your back. Wait, really, yes,

367
00:17:24.200 --> 00:17:26.839
<v Speaker 2>When it detects that a lambda is capturing a local variable,

368
00:17:26.880 --> 00:17:29.519
<v Speaker 2>it intercepts that variable. It takes it off the fast

369
00:17:29.640 --> 00:17:33.519
<v Speaker 2>temporary stack and hoists it into a hidden auto generated

370
00:17:33.559 --> 00:17:35.359
<v Speaker 2>class over in the heap warehouse.

371
00:17:35.759 --> 00:17:39.880
<v Speaker 1>That is wild. It quietly transforms a temporary value type

372
00:17:40.000 --> 00:17:42.680
<v Speaker 1>into a long lived reference type just to keep it

373
00:17:42.720 --> 00:17:43.559
<v Speaker 1>alive for the lambda.

374
00:17:43.759 --> 00:17:47.240
<v Speaker 2>It forcibly extends the variable's lifetime to match the life

375
00:17:47.240 --> 00:17:50.079
<v Speaker 2>span of the delegate. It will eventually be cleaned up

376
00:17:50.079 --> 00:17:53.119
<v Speaker 2>by the garbage collector. But it perfectly illustrates the hitting

377
00:17:53.200 --> 00:17:54.799
<v Speaker 2>cost of syntactic.

378
00:17:54.279 --> 00:17:55.839
<v Speaker 1>Sugar because it looks so simple.

379
00:17:56.200 --> 00:17:59.160
<v Speaker 2>Lambdas look wonderfully simple, just an arrow and some math,

380
00:17:59.519 --> 00:18:03.279
<v Speaker 2>but they can trigger complex heap allocations and garbage collection pressure.

381
00:18:03.720 --> 00:18:07.519
<v Speaker 2>This is precisely why c sharp seven introduce local methods.

382
00:18:07.880 --> 00:18:10.519
<v Speaker 2>The ability to define a fully named method and nested

383
00:18:10.599 --> 00:18:11.759
<v Speaker 2>inside another method.

384
00:18:11.880 --> 00:18:12.920
<v Speaker 1>So that's the alternative.

385
00:18:13.079 --> 00:18:16.559
<v Speaker 2>Right. Local methods can access those outer variables without forcing

386
00:18:16.559 --> 00:18:19.680
<v Speaker 2>the compiler to generate hidden heap classes, giving you a

387
00:18:19.759 --> 00:18:22.480
<v Speaker 2>highly efficient alternative when you don't actually need the pluggable

388
00:18:22.599 --> 00:18:23.519
<v Speaker 2>nature of a delegate.

389
00:18:23.799 --> 00:18:27.680
<v Speaker 1>The languid is literally reorganizing your memory management to accommodate

390
00:18:27.720 --> 00:18:29.880
<v Speaker 1>your logic, but you have to understand the trick so

391
00:18:29.920 --> 00:18:34.039
<v Speaker 1>you don't abuse it, which brings us to the ultimate

392
00:18:34.119 --> 00:18:38.119
<v Speaker 1>synthesis of everything we've discussed today, taking these floating behaviors

393
00:18:38.160 --> 00:18:42.519
<v Speaker 1>and applying them to massive data sets. Section four iterators

394
00:18:42.559 --> 00:18:43.279
<v Speaker 1>and LANQ.

395
00:18:43.799 --> 00:18:47.720
<v Speaker 2>This is where c Sharp's design philosophy achieves its greatest leverage.

396
00:18:48.279 --> 00:18:51.319
<v Speaker 2>It begins with iterators. If you need to generate a

397
00:18:51.359 --> 00:18:55.680
<v Speaker 2>massive sequence of numbers, say the Fibonacci sequence, you don't

398
00:18:55.680 --> 00:18:58.480
<v Speaker 2>have to calculate a million numbers, load them all into

399
00:18:58.519 --> 00:19:01.920
<v Speaker 2>a giant array in memory, and hand the heavier ray back.

400
00:19:02.559 --> 00:19:06.119
<v Speaker 2>You can write an iterator method using the yield return statement.

401
00:19:06.279 --> 00:19:09.759
<v Speaker 1>And the yield return statement is like another compiler magic trick.

402
00:19:10.200 --> 00:19:12.680
<v Speaker 1>The book explains that it transforms your method into a

403
00:19:12.720 --> 00:19:13.480
<v Speaker 1>state machine.

404
00:19:13.519 --> 00:19:14.720
<v Speaker 2>Exactly a state machine.

405
00:19:14.839 --> 00:19:17.000
<v Speaker 1>The code doesn't just run top to bottom and finish.

406
00:19:17.440 --> 00:19:20.480
<v Speaker 1>It runs until it hits yield, return hands the calculated

407
00:19:20.519 --> 00:19:22.319
<v Speaker 1>value back to the caller, and then it just freezes.

408
00:19:22.680 --> 00:19:25.920
<v Speaker 1>It pauses its entire state in memory. It doesn't wake

409
00:19:26.000 --> 00:19:28.720
<v Speaker 1>up or calculate the next number until the caller specifically

410
00:19:28.759 --> 00:19:29.799
<v Speaker 1>sends a command.

411
00:19:29.480 --> 00:19:33.240
<v Speaker 2>Called move next, and that precise, paused state machine is

412
00:19:33.279 --> 00:19:37.480
<v Speaker 2>the foundation of LANQ language Integrated Query. L and Q

413
00:19:37.640 --> 00:19:40.759
<v Speaker 2>allows you to query collections of data in memory using

414
00:19:40.839 --> 00:19:43.720
<v Speaker 2>a syntax that reads very much like database SQL.

415
00:19:43.839 --> 00:19:45.720
<v Speaker 1>Use standard operators, right yeah.

416
00:19:45.480 --> 00:19:48.440
<v Speaker 2>Like where to filter out bad data, select to transform

417
00:19:48.440 --> 00:19:50.920
<v Speaker 2>what's left, and order by to sort the final results.

418
00:19:51.200 --> 00:19:54.839
<v Speaker 1>Here's where it gets really interesting, though. The absolute superpower

419
00:19:54.839 --> 00:19:59.000
<v Speaker 1>of l and Q is deferred execution or lazy evaluations.

420
00:19:59.039 --> 00:19:59.680
<v Speaker 2>It's brilliant.

421
00:20:00.079 --> 00:20:02.920
<v Speaker 1>The authors provide this amazing example. You have a list

422
00:20:02.920 --> 00:20:06.799
<v Speaker 1>of numbers. You write a complex LNQ query to filter

423
00:20:06.960 --> 00:20:09.440
<v Speaker 1>and sort that list, but you haven't actually asked to

424
00:20:09.480 --> 00:20:12.240
<v Speaker 1>see the results yet. You just define the instructions. Then

425
00:20:12.279 --> 00:20:14.599
<v Speaker 1>you sneak an extra element into the original list. You

426
00:20:14.599 --> 00:20:17.839
<v Speaker 1>add the number two. After that you run a forged

427
00:20:17.880 --> 00:20:20.359
<v Speaker 1>loop to actually look at the results of your query,

428
00:20:20.799 --> 00:20:24.039
<v Speaker 1>and that brand new number two is fully processed and

429
00:20:24.039 --> 00:20:25.000
<v Speaker 1>included in the output.

430
00:20:25.160 --> 00:20:28.359
<v Speaker 2>Because writing the query and executing the query are two

431
00:20:28.480 --> 00:20:32.440
<v Speaker 2>fundamentally disconnected events, the query is just a blueprint of intent.

432
00:20:32.920 --> 00:20:35.960
<v Speaker 2>It refuses to actually touch the data until the absolute

433
00:20:36.039 --> 00:20:38.920
<v Speaker 2>last possible millisecond when you force it to enumerate.

434
00:20:39.079 --> 00:20:42.200
<v Speaker 1>I love visualizing deferred execution like a conveyor belt at

435
00:20:42.200 --> 00:20:44.519
<v Speaker 1>a highly efficient custom sandwich shop.

436
00:20:44.599 --> 00:20:45.400
<v Speaker 2>Oh I like this.

437
00:20:45.799 --> 00:20:48.039
<v Speaker 1>Yeah. You walk in and you tell the first worker,

438
00:20:48.960 --> 00:20:51.319
<v Speaker 1>I only want the wheat bread. That's your wear filter.

439
00:20:51.720 --> 00:20:55.000
<v Speaker 1>You tell the next worker toast it. That's your select transformation.

440
00:20:55.599 --> 00:20:58.480
<v Speaker 1>You tell the last worker put the biggest sandwiches first.

441
00:20:58.839 --> 00:21:03.240
<v Speaker 1>That's your order buy. You have built this intricate logic pipeline,

442
00:21:03.680 --> 00:21:07.240
<v Speaker 1>but the workers haven't sliced a single piece of bread yet.

443
00:21:07.440 --> 00:21:10.440
<v Speaker 1>They are just standing there frozen. They don't consume any ingredients,

444
00:21:10.440 --> 00:21:13.079
<v Speaker 1>They don't expand any energy until the customer at the

445
00:21:13.240 --> 00:21:15.920
<v Speaker 1>very end of the line finally opens their mouth and says,

446
00:21:16.039 --> 00:21:19.200
<v Speaker 1>I'll take the next sandwich. That is the forge loop,

447
00:21:19.279 --> 00:21:22.440
<v Speaker 1>and then it starts exactly Only then does the conveyor

448
00:21:22.440 --> 00:21:25.720
<v Speaker 1>belt turn on and it processes exactly one sandwich through

449
00:21:25.720 --> 00:21:26.799
<v Speaker 1>the entire pipeline.

450
00:21:26.880 --> 00:21:30.839
<v Speaker 2>The efficiency of that decoupling is staggering. If you construct

451
00:21:30.839 --> 00:21:33.480
<v Speaker 2>an l in Q query to process a database of

452
00:21:33.559 --> 00:21:36.880
<v Speaker 2>ten million records, but your user interface only ever asks

453
00:21:36.920 --> 00:21:40.039
<v Speaker 2>to display the first three results. The system only processes

454
00:21:40.079 --> 00:21:40.759
<v Speaker 2>three records.

455
00:21:40.759 --> 00:21:41.640
<v Speaker 1>It doesn't do the rest.

456
00:21:41.720 --> 00:21:45.319
<v Speaker 2>No, it doesn't waste precious CPU cycles and heap memory,

457
00:21:45.359 --> 00:21:47.960
<v Speaker 2>rendering a massive ten million item list that you will

458
00:21:47.960 --> 00:21:51.000
<v Speaker 2>never look at. It pulls data through the pipeline purely

459
00:21:51.039 --> 00:21:51.559
<v Speaker 2>on demand.

460
00:21:51.720 --> 00:21:55.319
<v Speaker 1>It is incredibly elegant, and it really brings this entire

461
00:21:55.440 --> 00:21:58.960
<v Speaker 1>exploration full circle. I mean, we started at the bedrock

462
00:21:59.039 --> 00:22:03.119
<v Speaker 1>physical reality of memory, the strict cafeteria trays of the stack,

463
00:22:03.200 --> 00:22:04.880
<v Speaker 1>and the sprawling warehouse of the heat.

464
00:22:05.000 --> 00:22:06.519
<v Speaker 2>We covered a lot of ground.

465
00:22:06.200 --> 00:22:08.680
<v Speaker 1>We really did. We saw how the physics of base

466
00:22:08.720 --> 00:22:11.759
<v Speaker 1>two processors create math quirks that we have to actively

467
00:22:11.799 --> 00:22:15.759
<v Speaker 1>manage with types like decimal. We untangled the logic traps

468
00:22:15.759 --> 00:22:19.319
<v Speaker 1>of closures, revealing how the compiler secretly hoists variables to

469
00:22:19.400 --> 00:22:23.039
<v Speaker 1>keep our lambdas alive. And finally we arrived at the lazy,

470
00:22:23.400 --> 00:22:27.599
<v Speaker 1>highly efficient conveyor belts of LNQ, which let us express

471
00:22:27.960 --> 00:22:31.400
<v Speaker 1>massive data operations with just a few intuitive lines of code,

472
00:22:31.680 --> 00:22:34.440
<v Speaker 1>completely abstracted away from the raw memory underneath.

473
00:22:34.519 --> 00:22:36.720
<v Speaker 2>It is a profound journey from the bare metal to

474
00:22:36.759 --> 00:22:38.799
<v Speaker 2>the high level abstract and to.

475
00:22:38.720 --> 00:22:41.279
<v Speaker 1>You listening right now, Whether you spend your day's writing

476
00:22:41.279 --> 00:22:44.400
<v Speaker 1>code or you're just deeply curious about the digital infrastructure

477
00:22:44.440 --> 00:22:49.000
<v Speaker 1>of our world. Mastering these concepts is powerful. Knowing exactly

478
00:22:49.079 --> 00:22:52.640
<v Speaker 1>why a simple subtraction equation fails to equal zero, or

479
00:22:52.680 --> 00:22:55.200
<v Speaker 1>knowing the mechanism of how a system can freeze its

480
00:22:55.200 --> 00:22:58.920
<v Speaker 1>state and delay doing work until the exact second it's needed.

481
00:22:59.240 --> 00:23:02.160
<v Speaker 1>It sharpens your critical thinking. It reminds you that underneath

482
00:23:02.200 --> 00:23:05.720
<v Speaker 1>every sleek app, every seamless interface, there is a shifting

483
00:23:05.839 --> 00:23:11.519
<v Speaker 1>architecture making microscopic, highly consequential decisions every single nanosecond.

484
00:23:11.559 --> 00:23:14.839
<v Speaker 2>I want to leave you with one final, slightly provocative

485
00:23:14.880 --> 00:23:17.920
<v Speaker 2>thought to chew on. We have spent this entire deep

486
00:23:18.000 --> 00:23:21.720
<v Speaker 2>dive examining how s sharp goes to extraordinary lengths to

487
00:23:21.759 --> 00:23:25.000
<v Speaker 2>protect you right. It offers strict type safety, It manages

488
00:23:25.039 --> 00:23:28.519
<v Speaker 2>your memory with the garbage collector, It diffuses null reference

489
00:23:28.559 --> 00:23:32.200
<v Speaker 2>panics with elvis operators, and it saves resources with lazy execution.

490
00:23:32.680 --> 00:23:34.599
<v Speaker 2>But tucked away in the text is a brief mention

491
00:23:34.680 --> 00:23:36.880
<v Speaker 2>of an advanced topic unsafe code and pointer.

492
00:23:37.000 --> 00:23:39.519
<v Speaker 1>Oh yeah, the unsafe zone, yes.

493
00:23:40.039 --> 00:23:42.960
<v Speaker 2>Se sharp actually allows you, if you explicitly choose to

494
00:23:42.960 --> 00:23:46.799
<v Speaker 2>do so, to write a block of code marked is unsafe.

495
00:23:46.839 --> 00:23:49.279
<v Speaker 2>Inside that block, the safety nets are ripped away, the

496
00:23:49.480 --> 00:23:53.319
<v Speaker 2>garbage collector steps back. You are permitted to use raw

497
00:23:53.559 --> 00:23:57.160
<v Speaker 2>direct memory pointers exactly as you would in an unforgiving

498
00:23:57.200 --> 00:24:00.759
<v Speaker 2>lower level language like C plus plus. So the question

499
00:24:00.880 --> 00:24:04.960
<v Speaker 2>is if language architects spend decades designing these brilliant safeguards

500
00:24:04.960 --> 00:24:08.720
<v Speaker 2>to maximize our productivity, what happens when you actively choose

501
00:24:08.759 --> 00:24:12.119
<v Speaker 2>to step outside those boundaries. When does the relentless quest

502
00:24:12.160 --> 00:24:15.559
<v Speaker 2>for absolute raw performance force us to abandon the very

503
00:24:15.680 --> 00:24:18.599
<v Speaker 2>tools that keep our system stable? And are you prepared

504
00:24:18.599 --> 00:24:21.119
<v Speaker 2>to build your own walls when the invisible workers leave?

505
00:24:21.440 --> 00:24:24.079
<v Speaker 1>That is a phenomenal question. The shifting walls of the

506
00:24:24.079 --> 00:24:26.480
<v Speaker 1>house we talked about at the beginning, they only protect

507
00:24:26.519 --> 00:24:28.640
<v Speaker 1>you as long as you stay inside them. The second

508
00:24:28.680 --> 00:24:30.799
<v Speaker 1>you step out into the unsafe zone, the blueprints are

509
00:24:30.920 --> 00:24:33.079
<v Speaker 1>entirely yours, and you better hope your math is perfect.

510
00:24:33.279 --> 00:24:35.519
<v Speaker 1>Thank you all for taking this GEEP dive with us today.

511
00:24:35.799 --> 00:24:38.359
<v Speaker 1>Keep asking questions, keep looking under the hood, and we

512
00:24:38.400 --> 00:24:39.279
<v Speaker 1>will see you next time,
