SlideShare une entreprise Scribd logo
@davidwengier
Lowering in C#
What’s really going on in your code?
David Wengier
Microsoft
NDC { Oslo }
2019
@davidwengier
foreach (int item in listOfInts)
{
// do something with item
}
for (int i = 0; i < listOfInts.Count; i++)
{
int item = listOfInts[i];
// do something with item
}
int i = 0;
while (i < listOfInts.Count)
{
int item = listOfInts[i];
// do something with item
i++;
}
int i = 0;
again:
int item = listOfInts[i];
// do something with item
i++;
if (i < listOfInts.Count)
{
goto again;
}
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: callvirt instance !0 class
[mscorlib]List`1<int32>::get_Item(int32)
IL_002b: pop
IL_002c: ldloc.1
IL_002d: ldc.i4.1
IL_002e: add
IL_002f: stloc.1
IL_0030: ldloc.1
IL_0031: ldloc.0
IL_0032: callvirt instance int32 class
[mscorlib]List`1<int32>::get_Count()
IL_0037: blt.s IL_0024
What is lowering?
IL
foreach
for
while
gotogoto
while
for
foreach
@davidwengier
What is lowering?
“A common technique … is to have the compiler
“lower” from high-level language features to low-level
language features in the same language.”
Eric Lippert
https://ericlippert.com/2014/04/28/lowering-in-language-design-part-one/
@davidwengier
LINQ
from c in customers
where c.Country == “AU”
select c;
@davidwengier
LINQ
customers.Where(c => c.Country == “AU”)
.Select(c => c);
@davidwengier
LINQ
Enumerable.Select(
Enumerable.Where(customers,
c => c.Country == “AU”),
c => c);
@davidwengier
LINQ
Enumerable.Select(
Enumerable.Where(customers, FilterCustomers),
SelectCustomer);
bool FilterCustomers(Customer c)
{
return c.Country == “AU”;
}
Customer SelectCustomer(Customer c)
{
return c;
}
@davidwengier
var message = "NDC Oslo";
decimal message = 5M;
string message = "NDC " + "Oslo";
string message = part1 + part2;
@davidwengier
Why do I want to know?
string message = "You have " + count + " items";
string message = $"You have {count} items";
string message = string.Format("You have {0} items",
count);
@davidwengier
foreach
foreach (int m in values)
{
Console.WriteLine(m);
}
@davidwengier
IEnumerable
interface IEnumerable
{
IEnumerator GetEnumerator();
}
interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
interface IEnumerable<T> : IEnumerable
{
new IEnumerator<T> GetEnumerator();
}
interface IEnumerator<T> : IEnumerator, IDisposable
{
new T Current { get; }
}
@davidwengier
foreach
{
var e = values.GetEnumerator();
try
{
int m;
while (e.MoveNext())
{
m = (int)(int)e.Current;
Console.WriteLine(m);
}
}
finally
{
if (e != null && e is IDisposable)
{
((IDisposable)e).Dispose();
}
}
}
object[] v = new [] { 1, 2 };
Write(v);
void Write(object[] arr)
{
foreach (int s in arr)
{
Console.WriteLine(s);
}
}
Person[] v = new [] { Empl(),..};
Write(v);
void Write(Person[] arr)
{
foreach (Customer c in arr)
{
Handle(c);
}
}
@davidwengier
foreach (C# 5+)
{
var e = values.GetEnumerator();
try
{
while (e.MoveNext())
{
int m;
m = (int)(int)e.Current;
Console.WriteLine(m);
}
}
finally
{
if (e != null && e is IDisposable)
{
((IDisposable)e).Dispose();
}
}
}
@davidwengier
Lambdas
public class C
{
public void M()
{
Action<string> act = x => Console.WriteLine(x);
act(“hello”);
}
}
@davidwengier
Lambdas
public class C
{
public void M()
{
Action<string> act = _act;
act(“hello”);
}
private void _act(string x)
{
Console.WriteLine(x);
}
}
@davidwengier
Lambdas
public class C
{
public void M()
{
ActHelper c = new ActHelper();
Action<string> act = c.act;
act(“hello”);
}
private class ActHelper
{
internal void act(string x)
{
Console.WriteLine(x);
}
}
}
@davidwengier
Lambdas
public class C
{
public void M()
{
if (ActHelper.Instance._act == null)
{
ActHelper.Instance._act = new Action<string>(ActHelper.Instance.act);
}
Action<string> act = ActHelper.Instance._act;
act(“hello”);
}
private sealed class ActHelper
{
public static readonly ActHelper Instance = new ActHelper();
public static Action<string> _act;
internal void act(string x)
{
Console.WriteLine(x);
}
}
}
@davidwengier
public class C
{
public void M()
{
Action<string> act = x => Console.WriteLine(x);
act(“Hello”);
}
}
public class C
{
public void M()
{
ActHelper c = new ActHelper();
Action<string> act = c.act;
act(“Hello”);
}
private sealed class ActHelper
{
internal void act(string x)
{
Console.WriteLine(x);
}
}
}
@davidwengier
public class C
{
public void M()
{
string y = “ World”;
Action<string> act = x => Console.WriteLine(x + y);
act(“Hello”);
}
}
public class C
{
public void M()
{
ActHelper c = new ActHelper();
Action<string> act = c.act;
act(“Hello”);
}
private sealed class ActHelper
{
internal void act(string x)
{
Console.WriteLine(x + y);
}
}
}
public class C
{
public void M()
{
ActHelper c = new ActHelper();
Action<string> act = c.act;
act(“Hello”);
}
private sealed class ActHelper
{
public string y;
internal void act(string x)
{
Console.WriteLine(x + y);
}
}
}
public class C
{
public void M()
{
ActHelper c = new ActHelper();
c.y = “ World”;
Action<string> act = c.act;
act(“Hello”);
}
private sealed class ActHelper
{
public string y;
internal void act(string x)
{
Console.WriteLine(x + y);
}
}
}
@davidwengier
public class C
{
public void M()
{
string y = “ World”;
Action<string> act = x => Console.WriteLine(x + y);
y = “ Fish”;
act(“Hello”);
}
}
public class C
{
public void M()
{
ActHelper c = new ActHelper();
c.y = “ World”;
Action<string> act = c.act;
act(“Hello”);
}
private sealed class ActHelper
{
public string y;
internal void act(string x)
{
Console.WriteLine(x + y);
}
}
}
@davidwengier
public class C
{
public void M()
{
string y = “ World”;
Action<string> act = x => Console.WriteLine(x + y);
y = “ Fish”;
act(“Hello”);
}
}
public class C
{
public void M()
{
ActHelper c = new ActHelper();
c.y = “ World”;
Action<string> act = c.act;
c.y = “ Fish”;
act(“Hello”);
}
private sealed class ActHelper
{
public string y;
internal void act(string x)
{
Console.WriteLine(x + y);
}
}
}
@davidwengier
Foreach and lambdas
List<Action> things = new List<Action>();
foreach (int m in values)
{
things.Add(() => Console.WriteLine(m));
}
@davidwengier
Foreach and lambdas
List<Action> things = new List<Action>();
{
var e = values.GetEnumerator();
try
{
ActHelper c = new ActHelper();
while (e.MoveNext())
{
c.m = (int)(int)e.Current;
things.Add(new Action(c.act));
}
}
finally
{
if (e != null && e is IDisposable) ((IDisposable)e).Dispose();
}
}
@davidwengier
Foreach and lambdas (C# 5+)
List<Action> things = new List<Action>();
{
var e = values.GetEnumerator();
try
{
while (e.MoveNext())
{
ActHelper c = new ActHelper();
c.m = (int)(int)e.Current;
things.Add(new Action(c.act));
}
}
finally
{
if (e != null && e is IDisposable) ((IDisposable)e).Dispose();
}
}
@davidwengier
public class C
{
private int z;
public void M()
{
string y = “ World”;
Action<string> act = x => Console.Write(x + y + z);
act(“Hello”);
}
}
public class C
{
private int z;
public void M()
{
ActHelper c = new ActHelper();
c.y = “ World”;
c._this = this;
c.act(“Hello”);
}
private sealed class ActHelper
{
public C _this;
public string y;
internal void act(string x)
{
Console.Write(x + y + _this.z);
}
}
}
@davidwengier
yield
foreach (int x in GetInts())
{
Console.WriteLine(x);
}
public IEnumerable<int> GetInts()
{
yield return 1;
yield return 2;
yield return 3;
yield return 4;
yield return 5;
}
@davidwengier
yield
using (IEnumerator<int> enumerator = this.GetInts().GetEnumerator())
{
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
}
public IEnumerable<int> GetInts()
{
return new GetIntsHelper(-2);
}
@davidwengier
yield
private class GetIntsHelper : IEnumerable<int>, IEnumerable, IEnumerator<int>, IDisposable, IEnumerator
{
private int _state;
private int _current;
private int _initialThreadId;
int IEnumerator<int>.Current { get { return this._current; } }
object IEnumerator.Current { get { return this._current; } }
public GetIntsHelper(int initialState)
{
this._state = initialState;
this._initialThreadId = Environment.CurrentManagedThreadId;
}
void IDisposable.Dispose()
{
}
@davidwengier
yield
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
GetIntsHelper result;
if (this._state == -2 && this._initialThreadId == Environment.CurrentManagedThreadId)
{
this._state = 0;
result = this;
}
else
{
result = new GetIntsHelper(0);
}
return result;
}
@davidwengier
yield
bool IEnumerator.MoveNext()
{
switch (this._state)
{
case 0:
this._state = -1;
this._current = 1;
this._state = 1;
return true;
case 1:
this._state = -1;
this._current = 2;
this._state = 2;
return true;
case 2:
this._state = -1;
this._current = 3;
this._state = 3;
return true;
case 3:
this._state = -1;
this._current = 4;
this._state = 4;
return true;
case 4:
this._state = -1;
this._current = 5;
this._state = 5;
return true;
case 5:
this._state = -1;
return false;
default:
return false;
@davidwengier
Yield states
-2 : GetEnumerator() hasn’t been called
-1 : Running – Getting the next value
0 : Before – MoveNext() hasn’t been called
1- 4 : Suspended – Waiting for a MoveNext() call
5 : After – Finished.
@davidwengier
yield
public IEnumerable<int> GetInts()
{
foreach (int x in Enumerable.Range(1, 10))
{
yield return x;
}
}
@davidwengier
yield
private IEnumerator<int> _wrap;
void IDisposable.Dispose()
{
if (this._state == -3 || this._state == 1)
{
this._Finally();
}
}
private void _Finally()
{
this._state = -1;
if (this._wrap != null)
{
this._wrap.Dispose();
}
}
@davidwengier
yield
bool IEnumerator.MoveNext()
{
try
{
// ... Next slide
}
catch
{
this.Dispose();
throw;
}
}
@davidwengier
yield
if (this._state == 0)
{
this._state = -1;
this._wrap = Enumerable.Range(1, 10).GetEnumerator();
this._state = -3;
}
else
{
if (this._state != 1) return false;
this._state = -3;
}
if (this._wrap.MoveNext())
{
this._current = (int)this._wrap.Current;
this._state = 1;
return true;
}
else
{
this._Finally();
this._wrap = null;
return false;
}
@davidwengier
Yield states
-3 : Running – Getting the next value
-2 : GetEnumerator() hasn’t been called
-1 : Running – Getting the range enumerator
0 : Before – MoveNext() hasn’t been called
1 : Suspended (and After) – Waiting for a MoveNext() call
@davidwengier
Captain planet
private int _min;
public void M()
{
int max = 5;
foreach (int x in GetInts(max))
{
Console.WriteLine(x);
}
}
public IEnumerable<int> GetInts(int max)
{
yield return 1;
foreach (int x in Enumerable.Range(this._min, max).OrderBy(i => i * this._min + max))
{
yield return x;
}
}
???
@davidwengier
Want to know more?
• Roslyn source code
• Your favourite decompiler
• http://sharplab.io
@davidwengier
Thank you!
Questions?
Comments?
Quemments?
@davidwengier

Contenu connexe

Tendances

Lessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL APILessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL API
Dirk-Jan Rutten
 
An intro to cqrs
An intro to cqrsAn intro to cqrs
An intro to cqrs
Neil Robbins
 
Dependency rejection and TDD without Mocks
Dependency rejection and TDD without MocksDependency rejection and TDD without Mocks
Dependency rejection and TDD without Mocks
Antya Dev
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Thomas Fuchs
 
jQuery quick tuts
jQuery quick tutsjQuery quick tuts
jQuery quick tuts
Nasa Vietnam
 
Dojo and Adobe AIR
Dojo and Adobe AIRDojo and Adobe AIR
Dojo and Adobe AIR
Nikolai Onken
 
Unbreakable: The Craft of Code
Unbreakable: The Craft of CodeUnbreakable: The Craft of Code
Unbreakable: The Craft of Code
Joe Morgan
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wild
Joe Morgan
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
David Rodenas
 
Granada_Perl_Workshop_2014_Google_API_Client
Granada_Perl_Workshop_2014_Google_API_ClientGranada_Perl_Workshop_2014_Google_API_Client
Granada_Perl_Workshop_2014_Google_API_Client
Alberto Jesús Gutiérrez Juanes
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
David Rodenas
 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React
Robert DeLuca
 
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
tdc-globalcode
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
Ignacio Martín
 
Adopting F# at SBTech
Adopting F# at SBTechAdopting F# at SBTech
Adopting F# at SBTech
Antya Dev
 
Typescript barcelona
Typescript barcelonaTypescript barcelona
Typescript barcelona
Christoffer Noring
 
React lecture
React lectureReact lecture
React lecture
Christoffer Noring
 
Open sourcing the store
Open sourcing the storeOpen sourcing the store
Open sourcing the store
Mike Nakhimovich
 
Backbone Basics with Examples
Backbone Basics with ExamplesBackbone Basics with Examples
Backbone Basics with Examples
Sergey Bolshchikov
 
The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210
Mahmoud Samir Fayed
 

Tendances (20)

Lessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL APILessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL API
 
An intro to cqrs
An intro to cqrsAn intro to cqrs
An intro to cqrs
 
Dependency rejection and TDD without Mocks
Dependency rejection and TDD without MocksDependency rejection and TDD without Mocks
Dependency rejection and TDD without Mocks
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
 
jQuery quick tuts
jQuery quick tutsjQuery quick tuts
jQuery quick tuts
 
Dojo and Adobe AIR
Dojo and Adobe AIRDojo and Adobe AIR
Dojo and Adobe AIR
 
Unbreakable: The Craft of Code
Unbreakable: The Craft of CodeUnbreakable: The Craft of Code
Unbreakable: The Craft of Code
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wild
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
 
Granada_Perl_Workshop_2014_Google_API_Client
Granada_Perl_Workshop_2014_Google_API_ClientGranada_Perl_Workshop_2014_Google_API_Client
Granada_Perl_Workshop_2014_Google_API_Client
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React
 
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
Adopting F# at SBTech
Adopting F# at SBTechAdopting F# at SBTech
Adopting F# at SBTech
 
Typescript barcelona
Typescript barcelonaTypescript barcelona
Typescript barcelona
 
React lecture
React lectureReact lecture
React lecture
 
Open sourcing the store
Open sourcing the storeOpen sourcing the store
Open sourcing the store
 
Backbone Basics with Examples
Backbone Basics with ExamplesBackbone Basics with Examples
Backbone Basics with Examples
 
The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210
 

Similaire à Lowering in C#: What really happens with your code?, from NDC Oslo 2019

Java весна 2013 лекция 2
Java весна 2013 лекция 2Java весна 2013 лекция 2
Java весна 2013 лекция 2
Technopark
 
OBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .pptOBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .ppt
SaadAsim11
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
Juan Pablo
 
C sharp 8
C sharp 8C sharp 8
C sharp 8
Germán Küber
 
Minicurso Android
Minicurso AndroidMinicurso Android
Minicurso Android
Mario Jorge Pereira
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
Chris Weldon
 
662305 10
662305 10662305 10
Scala on Your Phone
Scala on Your PhoneScala on Your Phone
Scala on Your Phone
Michael Galpin
 
Android Design Patterns
Android Design PatternsAndroid Design Patterns
Android Design Patterns
Godfrey Nolan
 
Mattbrenner
MattbrennerMattbrenner
Mattbrenner
Droidcon Berlin
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NET
tdc-globalcode
 
Infinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtilInfinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtil
Infinum
 
Ipc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseIpc: aidl sexy, not a curse
Ipc: aidl sexy, not a curse
Yonatan Levin
 
IPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curseIPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curse
Yonatan Levin
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
Dmitry Sheiko
 
Create a class BinarySearchTree- A class that implements the ADT binar.pdf
Create a class BinarySearchTree- A class that implements the ADT binar.pdfCreate a class BinarySearchTree- A class that implements the ADT binar.pdf
Create a class BinarySearchTree- A class that implements the ADT binar.pdf
shyamsunder1211
 
Pragmatic metaprogramming
Pragmatic metaprogrammingPragmatic metaprogramming
Pragmatic metaprogramming
Mårten Rånge
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
Leonid Maslov
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
Lorna Mitchell
 
New C# features
New C# featuresNew C# features
New C# features
Alexej Sommer
 

Similaire à Lowering in C#: What really happens with your code?, from NDC Oslo 2019 (20)

Java весна 2013 лекция 2
Java весна 2013 лекция 2Java весна 2013 лекция 2
Java весна 2013 лекция 2
 
OBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .pptOBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .ppt
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
 
C sharp 8
C sharp 8C sharp 8
C sharp 8
 
Minicurso Android
Minicurso AndroidMinicurso Android
Minicurso Android
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
662305 10
662305 10662305 10
662305 10
 
Scala on Your Phone
Scala on Your PhoneScala on Your Phone
Scala on Your Phone
 
Android Design Patterns
Android Design PatternsAndroid Design Patterns
Android Design Patterns
 
Mattbrenner
MattbrennerMattbrenner
Mattbrenner
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NET
 
Infinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtilInfinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtil
 
Ipc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseIpc: aidl sexy, not a curse
Ipc: aidl sexy, not a curse
 
IPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curseIPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curse
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Create a class BinarySearchTree- A class that implements the ADT binar.pdf
Create a class BinarySearchTree- A class that implements the ADT binar.pdfCreate a class BinarySearchTree- A class that implements the ADT binar.pdf
Create a class BinarySearchTree- A class that implements the ADT binar.pdf
 
Pragmatic metaprogramming
Pragmatic metaprogrammingPragmatic metaprogramming
Pragmatic metaprogramming
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
New C# features
New C# featuresNew C# features
New C# features
 

Dernier

Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptxMigration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
ervikas4
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
Bert Jan Schrijver
 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
Pedro J. Molina
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
What’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete RoadmapWhat’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete Roadmap
Envertis Software Solutions
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
Marcin Chrost
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
sjcobrien
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
XfilesPro
 
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
kalichargn70th171
 
DevOps Consulting Company | Hire DevOps Services
DevOps Consulting Company | Hire DevOps ServicesDevOps Consulting Company | Hire DevOps Services
DevOps Consulting Company | Hire DevOps Services
seospiralmantra
 
Boost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management AppsBoost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management Apps
Jhone kinadey
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
Maitrey Patel
 
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
kalichargn70th171
 
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
OnePlan Solutions
 
42 Ways to Generate Real Estate Leads - Sellxpert
42 Ways to Generate Real Estate Leads - Sellxpert42 Ways to Generate Real Estate Leads - Sellxpert
42 Ways to Generate Real Estate Leads - Sellxpert
vaishalijagtap12
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
Patrick Weigel
 
Kubernetes at Scale: Going Multi-Cluster with Istio
Kubernetes at Scale:  Going Multi-Cluster  with IstioKubernetes at Scale:  Going Multi-Cluster  with Istio
Kubernetes at Scale: Going Multi-Cluster with Istio
Severalnines
 
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
Luigi Fugaro
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid
 

Dernier (20)

Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptxMigration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
What’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete RoadmapWhat’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete Roadmap
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
 
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
 
DevOps Consulting Company | Hire DevOps Services
DevOps Consulting Company | Hire DevOps ServicesDevOps Consulting Company | Hire DevOps Services
DevOps Consulting Company | Hire DevOps Services
 
Boost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management AppsBoost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management Apps
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
 
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
 
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
 
42 Ways to Generate Real Estate Leads - Sellxpert
42 Ways to Generate Real Estate Leads - Sellxpert42 Ways to Generate Real Estate Leads - Sellxpert
42 Ways to Generate Real Estate Leads - Sellxpert
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
 
Kubernetes at Scale: Going Multi-Cluster with Istio
Kubernetes at Scale:  Going Multi-Cluster  with IstioKubernetes at Scale:  Going Multi-Cluster  with Istio
Kubernetes at Scale: Going Multi-Cluster with Istio
 
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
 

Lowering in C#: What really happens with your code?, from NDC Oslo 2019

  • 1. @davidwengier Lowering in C# What’s really going on in your code? David Wengier Microsoft NDC { Oslo } 2019
  • 2. @davidwengier foreach (int item in listOfInts) { // do something with item } for (int i = 0; i < listOfInts.Count; i++) { int item = listOfInts[i]; // do something with item } int i = 0; while (i < listOfInts.Count) { int item = listOfInts[i]; // do something with item i++; } int i = 0; again: int item = listOfInts[i]; // do something with item i++; if (i < listOfInts.Count) { goto again; } IL_0024: ldloc.0 IL_0025: ldloc.1 IL_0026: callvirt instance !0 class [mscorlib]List`1<int32>::get_Item(int32) IL_002b: pop IL_002c: ldloc.1 IL_002d: ldc.i4.1 IL_002e: add IL_002f: stloc.1 IL_0030: ldloc.1 IL_0031: ldloc.0 IL_0032: callvirt instance int32 class [mscorlib]List`1<int32>::get_Count() IL_0037: blt.s IL_0024 What is lowering? IL foreach for while gotogoto while for foreach
  • 3. @davidwengier What is lowering? “A common technique … is to have the compiler “lower” from high-level language features to low-level language features in the same language.” Eric Lippert https://ericlippert.com/2014/04/28/lowering-in-language-design-part-one/
  • 4. @davidwengier LINQ from c in customers where c.Country == “AU” select c;
  • 7. @davidwengier LINQ Enumerable.Select( Enumerable.Where(customers, FilterCustomers), SelectCustomer); bool FilterCustomers(Customer c) { return c.Country == “AU”; } Customer SelectCustomer(Customer c) { return c; }
  • 8. @davidwengier var message = "NDC Oslo"; decimal message = 5M; string message = "NDC " + "Oslo"; string message = part1 + part2;
  • 9. @davidwengier Why do I want to know? string message = "You have " + count + " items"; string message = $"You have {count} items"; string message = string.Format("You have {0} items", count);
  • 10. @davidwengier foreach foreach (int m in values) { Console.WriteLine(m); }
  • 11. @davidwengier IEnumerable interface IEnumerable { IEnumerator GetEnumerator(); } interface IEnumerator { object Current { get; } bool MoveNext(); void Reset(); } interface IEnumerable<T> : IEnumerable { new IEnumerator<T> GetEnumerator(); } interface IEnumerator<T> : IEnumerator, IDisposable { new T Current { get; } }
  • 12. @davidwengier foreach { var e = values.GetEnumerator(); try { int m; while (e.MoveNext()) { m = (int)(int)e.Current; Console.WriteLine(m); } } finally { if (e != null && e is IDisposable) { ((IDisposable)e).Dispose(); } } } object[] v = new [] { 1, 2 }; Write(v); void Write(object[] arr) { foreach (int s in arr) { Console.WriteLine(s); } } Person[] v = new [] { Empl(),..}; Write(v); void Write(Person[] arr) { foreach (Customer c in arr) { Handle(c); } }
  • 13. @davidwengier foreach (C# 5+) { var e = values.GetEnumerator(); try { while (e.MoveNext()) { int m; m = (int)(int)e.Current; Console.WriteLine(m); } } finally { if (e != null && e is IDisposable) { ((IDisposable)e).Dispose(); } } }
  • 14. @davidwengier Lambdas public class C { public void M() { Action<string> act = x => Console.WriteLine(x); act(“hello”); } }
  • 15. @davidwengier Lambdas public class C { public void M() { Action<string> act = _act; act(“hello”); } private void _act(string x) { Console.WriteLine(x); } }
  • 16. @davidwengier Lambdas public class C { public void M() { ActHelper c = new ActHelper(); Action<string> act = c.act; act(“hello”); } private class ActHelper { internal void act(string x) { Console.WriteLine(x); } } }
  • 17. @davidwengier Lambdas public class C { public void M() { if (ActHelper.Instance._act == null) { ActHelper.Instance._act = new Action<string>(ActHelper.Instance.act); } Action<string> act = ActHelper.Instance._act; act(“hello”); } private sealed class ActHelper { public static readonly ActHelper Instance = new ActHelper(); public static Action<string> _act; internal void act(string x) { Console.WriteLine(x); } } }
  • 18. @davidwengier public class C { public void M() { Action<string> act = x => Console.WriteLine(x); act(“Hello”); } } public class C { public void M() { ActHelper c = new ActHelper(); Action<string> act = c.act; act(“Hello”); } private sealed class ActHelper { internal void act(string x) { Console.WriteLine(x); } } }
  • 19. @davidwengier public class C { public void M() { string y = “ World”; Action<string> act = x => Console.WriteLine(x + y); act(“Hello”); } } public class C { public void M() { ActHelper c = new ActHelper(); Action<string> act = c.act; act(“Hello”); } private sealed class ActHelper { internal void act(string x) { Console.WriteLine(x + y); } } } public class C { public void M() { ActHelper c = new ActHelper(); Action<string> act = c.act; act(“Hello”); } private sealed class ActHelper { public string y; internal void act(string x) { Console.WriteLine(x + y); } } } public class C { public void M() { ActHelper c = new ActHelper(); c.y = “ World”; Action<string> act = c.act; act(“Hello”); } private sealed class ActHelper { public string y; internal void act(string x) { Console.WriteLine(x + y); } } }
  • 20. @davidwengier public class C { public void M() { string y = “ World”; Action<string> act = x => Console.WriteLine(x + y); y = “ Fish”; act(“Hello”); } } public class C { public void M() { ActHelper c = new ActHelper(); c.y = “ World”; Action<string> act = c.act; act(“Hello”); } private sealed class ActHelper { public string y; internal void act(string x) { Console.WriteLine(x + y); } } }
  • 21. @davidwengier public class C { public void M() { string y = “ World”; Action<string> act = x => Console.WriteLine(x + y); y = “ Fish”; act(“Hello”); } } public class C { public void M() { ActHelper c = new ActHelper(); c.y = “ World”; Action<string> act = c.act; c.y = “ Fish”; act(“Hello”); } private sealed class ActHelper { public string y; internal void act(string x) { Console.WriteLine(x + y); } } }
  • 22. @davidwengier Foreach and lambdas List<Action> things = new List<Action>(); foreach (int m in values) { things.Add(() => Console.WriteLine(m)); }
  • 23. @davidwengier Foreach and lambdas List<Action> things = new List<Action>(); { var e = values.GetEnumerator(); try { ActHelper c = new ActHelper(); while (e.MoveNext()) { c.m = (int)(int)e.Current; things.Add(new Action(c.act)); } } finally { if (e != null && e is IDisposable) ((IDisposable)e).Dispose(); } }
  • 24. @davidwengier Foreach and lambdas (C# 5+) List<Action> things = new List<Action>(); { var e = values.GetEnumerator(); try { while (e.MoveNext()) { ActHelper c = new ActHelper(); c.m = (int)(int)e.Current; things.Add(new Action(c.act)); } } finally { if (e != null && e is IDisposable) ((IDisposable)e).Dispose(); } }
  • 25. @davidwengier public class C { private int z; public void M() { string y = “ World”; Action<string> act = x => Console.Write(x + y + z); act(“Hello”); } } public class C { private int z; public void M() { ActHelper c = new ActHelper(); c.y = “ World”; c._this = this; c.act(“Hello”); } private sealed class ActHelper { public C _this; public string y; internal void act(string x) { Console.Write(x + y + _this.z); } } }
  • 26. @davidwengier yield foreach (int x in GetInts()) { Console.WriteLine(x); } public IEnumerable<int> GetInts() { yield return 1; yield return 2; yield return 3; yield return 4; yield return 5; }
  • 27. @davidwengier yield using (IEnumerator<int> enumerator = this.GetInts().GetEnumerator()) { while (enumerator.MoveNext()) { Console.WriteLine(enumerator.Current); } } public IEnumerable<int> GetInts() { return new GetIntsHelper(-2); }
  • 28. @davidwengier yield private class GetIntsHelper : IEnumerable<int>, IEnumerable, IEnumerator<int>, IDisposable, IEnumerator { private int _state; private int _current; private int _initialThreadId; int IEnumerator<int>.Current { get { return this._current; } } object IEnumerator.Current { get { return this._current; } } public GetIntsHelper(int initialState) { this._state = initialState; this._initialThreadId = Environment.CurrentManagedThreadId; } void IDisposable.Dispose() { }
  • 29. @davidwengier yield IEnumerator<int> IEnumerable<int>.GetEnumerator() { GetIntsHelper result; if (this._state == -2 && this._initialThreadId == Environment.CurrentManagedThreadId) { this._state = 0; result = this; } else { result = new GetIntsHelper(0); } return result; }
  • 30. @davidwengier yield bool IEnumerator.MoveNext() { switch (this._state) { case 0: this._state = -1; this._current = 1; this._state = 1; return true; case 1: this._state = -1; this._current = 2; this._state = 2; return true; case 2: this._state = -1; this._current = 3; this._state = 3; return true; case 3: this._state = -1; this._current = 4; this._state = 4; return true; case 4: this._state = -1; this._current = 5; this._state = 5; return true; case 5: this._state = -1; return false; default: return false;
  • 31. @davidwengier Yield states -2 : GetEnumerator() hasn’t been called -1 : Running – Getting the next value 0 : Before – MoveNext() hasn’t been called 1- 4 : Suspended – Waiting for a MoveNext() call 5 : After – Finished.
  • 32. @davidwengier yield public IEnumerable<int> GetInts() { foreach (int x in Enumerable.Range(1, 10)) { yield return x; } }
  • 33. @davidwengier yield private IEnumerator<int> _wrap; void IDisposable.Dispose() { if (this._state == -3 || this._state == 1) { this._Finally(); } } private void _Finally() { this._state = -1; if (this._wrap != null) { this._wrap.Dispose(); } }
  • 34. @davidwengier yield bool IEnumerator.MoveNext() { try { // ... Next slide } catch { this.Dispose(); throw; } }
  • 35. @davidwengier yield if (this._state == 0) { this._state = -1; this._wrap = Enumerable.Range(1, 10).GetEnumerator(); this._state = -3; } else { if (this._state != 1) return false; this._state = -3; } if (this._wrap.MoveNext()) { this._current = (int)this._wrap.Current; this._state = 1; return true; } else { this._Finally(); this._wrap = null; return false; }
  • 36. @davidwengier Yield states -3 : Running – Getting the next value -2 : GetEnumerator() hasn’t been called -1 : Running – Getting the range enumerator 0 : Before – MoveNext() hasn’t been called 1 : Suspended (and After) – Waiting for a MoveNext() call
  • 37. @davidwengier Captain planet private int _min; public void M() { int max = 5; foreach (int x in GetInts(max)) { Console.WriteLine(x); } } public IEnumerable<int> GetInts(int max) { yield return 1; foreach (int x in Enumerable.Range(this._min, max).OrderBy(i => i * this._min + max)) { yield return x; } } ???
  • 38. @davidwengier Want to know more? • Roslyn source code • Your favourite decompiler • http://sharplab.io

Notes de l'éditeur

  1. Invented a language, having a language design meeting. Someone suggests “foreach”. Everyone agrees, except the guy in the corner. Lowering. He’s lazy. “why not just use a for loop”
  2. Because I love it! One abstraction layer deeper Debugging Performance
  3. Lets look at one of those previous examples in detail.
  4. Lets look at one of those previous examples in detail.
  5. Simplified generic version. There are specific overloads for arrays, stirngs etc. No type on GetEnumerator. Duck typing. Not really var, the compiler works it out, I just can’t express it. Also checks for implicit implementations and casts to IEnumerable. If necessary. Two casts. One for item type, one for the type of the loop variable (because designed before generics, eg ArrayList). Means you can loop through objects, and ask for strings. EG ANIMATIONS!! Those casts could fail. Disposable is optional. Compiler will work out whether to include it (and will leave off the try..finally entirely if it can Note the brackets to introduce a new scope This is the C# 4 and below version.
  6. Subtle difference. Variable declaration inside while loop. This is a breaking change. Why? Answer is closures, which brings us to our next bit of lowering.
  7. To talk about closures, I think its easiest to talk about lambdas.
  8. This is what it logically does, however this has a problem. Without knowing what Console.WriteLine does, and depending on what is passed in, we can’t guarantee this doesn’t hold a reference to class C. So instead this is what the compiler does:
  9. By using a new class, even if an instance is held in memory the compiler knows its as small as it can be. Obviously these method and class names would be different. In fact, compiler deliberately uses names that are invalid C#
  10. This is _really_ what the compiler does though. Apologies for the size.. Various optimizations. So far so good? Cool. The other thing we can do wth lambdas and delegates is create closures.
  11. Lets go back to our original lamba, but make a small change. This action now creates a closure over y. Now the compiler has to put y in the new class, and store a reference to it. This looks like this.
  12. Lets go back to our original lamba, but make a small change. This action now creates a closure over y. Now the compiler has to put y in the new class, and store a reference to it. This looks like this.
  13. So, can you see the problem? It doesn’t matter when you create the delegate, we’ve capture the variable y, not the value of the variable y. So the code uses the value of the variable y as at the time it is executed.
  14. So, can you see the problem? It doesn’t matter when you create the delegate, we’ve capture the variable y, not the value of the variable y. So the code uses the value of the variable y as at the time it is executed.
  15. So lets revisit our foreach loop, but now add a lambda in the middle. We’ll just collect a list of things to do later.. Call it poor mans async 
  16. Now this gets expanded as we know. I’ve highlighted the new bits.
  17. In C# 5 however, we now move the declaration of m inside the loop, therefore we don’t have a problem.. Essentially when C# 4 came out everyone was so lambda happy that it exposed this quirk. Why did they do it the other way first? Matches the “for” semantics, of having one loop variable that is redefined. Just that with “for” its much more obvious, because the user is writing that redefinition.
  18. One last word on closures, is what the difference is when we close over a class level field, property, method etc. The field is not hoisted, instead the helper class has a reference to the original object. This can potentially lead to memory leaks. Solved by introducing local variables to capture the value, though does change the semantics (value capture not variable capture)
  19. Kinda still on foreaches, lets look at the yield statement. Things get pretty tricky with this one.. So any questions before we continue?
  20. The foreach part we know, and GetInts is still a method that returns an enumerable. The content of GetInts has been moved to a new class though, like we saw with lambdas. Lets look at that class
  21. So, it implements a few interfaces. And mose of these things are obvious. It captures the thread id, which we’ll see later is used for thread safety. It implements Idisposable as a just in case, and in this case doesn’t need to dispose anything. Will see more later. Current we’ve seen before from Ienumerable, and there is a local variable to track it. And it stores state. As you might know, or have guessed, the yield enumerator uses a state machine. The intial state, if you remember, is -2
  22. Here is the GetEnumerator method. This is where we do some thread checking. So if GetEnumerator() is called from the same thread, and we have our initial state, then this is the thing we use. This is what allows our class to be an enumerable, that can be returned from GetInts(), and an enumerator, that can do the enumeration. This sets the state to 0. If something else calls GetEnumerator(), or we’re in a different state, then return a new instance with a 0 initial state.
  23. Pretty basic state machine. Essentially its an unrolled loop, which makes sense because if you think about our yield statement, that was too. 4 states: Before (-2, 0), Running (-1), Suspended and After (positive integers) Questions? More realistic uses get a bit harder, so lets look at one.
  24. This is a bit more typical, where in your method you’d be looping through something else, and yield returning. If the yield return unrolls the loop, well what happens when you put a loop in your loop unrolling? Lets look at the differences.
  25. A new Enumerator field, called wrap. In Dispose we call Finally, and that disposes of the wrapped enumerator. The weird empty try..finally block, I cannot explain!. Could be a decompilation problem.
  26. Just to save space on the next slide, MoveNext has nothing new that’s interesting.. Just a dispose call in a catch
  27. Hopefully still big enough.. This looks very different! But its still a state machine. Initial state is 0, so first we set state to -3 (another type of “Running” - about get next), and get a reference to the range enumerator. Then we call MoveNext, set state to 1. Each call to this MoveNext calls the wrapped MoveNext, until we run out. At the end we call Finally() again. -1 is running the GetEnumerator, -3 is running the MoveNext
  28. This instance doesn’t really have an “After” because it doesn’t know when to stop on its own, it simply passes calls on to the wrapped enumerator, and hence relies on that enumerators After state.
  29. And of course you can combine these things, by having multiple yield returns, the iterator can close over variables, and fields, and can include a lambda that does the same! This is why lowering is good. No need to implement all of this lot in IL. We know this bit will become a class, closing over some things.. And this… At the end it will just be classes with straight forward code, containing pretty much just gotos