SlideShare a Scribd company logo

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

Slides from my talk given at NDC Oslo, about what the compiler does when you write a foreach loop, among others.

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

1 of 39
Download to read offline
@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);

Recommended

A (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project FilesA (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project FilesDavid Wengier
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projectsIgnacio Martín
 
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...Lviv Startup Club
 
[AngularJS] From Angular to Mobile in 30 minutes
[AngularJS] From Angular to Mobile in 30 minutes[AngularJS] From Angular to Mobile in 30 minutes
[AngularJS] From Angular to Mobile in 30 minutesGlobant
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Ontico
 

More Related Content

What's hot

Lessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL APILessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL APIDirk-Jan Rutten
 
Dependency rejection and TDD without Mocks
Dependency rejection and TDD without MocksDependency rejection and TDD without Mocks
Dependency rejection and TDD without MocksAntya 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 2KThomas Fuchs
 
Unbreakable: The Craft of Code
Unbreakable: The Craft of CodeUnbreakable: The Craft of Code
Unbreakable: The Craft of CodeJoe Morgan
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wildJoe Morgan
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersDavid Rodenas
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorDavid 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 es6Ignacio Martín
 
Adopting F# at SBTech
Adopting F# at SBTechAdopting F# at SBTech
Adopting F# at SBTechAntya Dev
 
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 210Mahmoud Samir Fayed
 

What's hot (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
 

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

Java весна 2013 лекция 2
Java весна 2013 лекция 2Java весна 2013 лекция 2
Java весна 2013 лекция 2Technopark
 
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
 
Crud pada eclipse android menggunakan database sqlite
Crud pada eclipse android menggunakan database sqliteCrud pada eclipse android menggunakan database sqlite
Crud pada eclipse android menggunakan database sqlitefadliyanto badu
 
Android Design Patterns
Android Design PatternsAndroid Design Patterns
Android Design PatternsGodfrey Nolan
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETtdc-globalcode
 
Infinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtilInfinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtilInfinum
 
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 curseYonatan Levin
 
Ipc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseIpc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseYonatan Levin
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry 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.pdfshyamsunder1211
 
Pragmatic metaprogramming
Pragmatic metaprogrammingPragmatic metaprogramming
Pragmatic metaprogrammingMårten Rånge
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2Leonid Maslov
 

Similar to 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
 
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
 
Crud pada eclipse android menggunakan database sqlite
Crud pada eclipse android menggunakan database sqliteCrud pada eclipse android menggunakan database sqlite
Crud pada eclipse android menggunakan database sqlite
 
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 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
 
Ipc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseIpc: aidl sexy, not a curse
Ipc: aidl 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
 

Recently uploaded

Industry 4.0: Building the Unified Namespace with Confluent, HiveMQ and Spark...
Industry 4.0: Building the Unified Namespace with Confluent, HiveMQ and Spark...Industry 4.0: Building the Unified Namespace with Confluent, HiveMQ and Spark...
Industry 4.0: Building the Unified Namespace with Confluent, HiveMQ and Spark...confluent
 
Steps to Build a PWA with Odoo.pdf
Steps to Build a PWA with Odoo.pdfSteps to Build a PWA with Odoo.pdf
Steps to Build a PWA with Odoo.pdfayushinwizards
 
maximum subarray ppt for killing camp students
maximum subarray ppt for killing camp studentsmaximum subarray ppt for killing camp students
maximum subarray ppt for killing camp studentsssuser82c38d
 
Self scaling Multi cloud nomad workloads
Self scaling Multi cloud nomad workloadsSelf scaling Multi cloud nomad workloads
Self scaling Multi cloud nomad workloadsBram Vogelaar
 
Les02 Restricting and Sorting Data using SQL.ppt
Les02 Restricting and Sorting Data using SQL.pptLes02 Restricting and Sorting Data using SQL.ppt
Les02 Restricting and Sorting Data using SQL.pptDrZeeshanBhatti
 
Open Sprintera (Where Open Source Sparks a Sprint of Possibilities)
Open Sprintera (Where Open Source Sparks a Sprint of Possibilities)Open Sprintera (Where Open Source Sparks a Sprint of Possibilities)
Open Sprintera (Where Open Source Sparks a Sprint of Possibilities)GDSCNiT
 
100 TOOLS TO MEASURE AND ANALYSE YOUR DIGITAL MARKETING EFFORTS
100 TOOLS TO MEASURE AND ANALYSE YOUR DIGITAL MARKETING EFFORTS100 TOOLS TO MEASURE AND ANALYSE YOUR DIGITAL MARKETING EFFORTS
100 TOOLS TO MEASURE AND ANALYSE YOUR DIGITAL MARKETING EFFORTSi-engage
 
India's_Generative_AI_Startup_Landscape_Report_2023_Inc42 (1).pdf
India's_Generative_AI_Startup_Landscape_Report_2023_Inc42 (1).pdfIndia's_Generative_AI_Startup_Landscape_Report_2023_Inc42 (1).pdf
India's_Generative_AI_Startup_Landscape_Report_2023_Inc42 (1).pdfgranitesrijan
 
unit 1 lecture 1 - Introduction - Software Engineering Myths.pdf
unit 1 lecture 1 - Introduction - Software Engineering Myths.pdfunit 1 lecture 1 - Introduction - Software Engineering Myths.pdf
unit 1 lecture 1 - Introduction - Software Engineering Myths.pdfStephenTec
 
Embracing Change - The Impact of Generative AI on Strategic Portfolio Management
Embracing Change - The Impact of Generative AI on Strategic Portfolio ManagementEmbracing Change - The Impact of Generative AI on Strategic Portfolio Management
Embracing Change - The Impact of Generative AI on Strategic Portfolio ManagementOnePlan Solutions
 
AUTOKEYUNLOCKER-BRANDS-SUPPORT-STANDARD-VERSION.pdf
AUTOKEYUNLOCKER-BRANDS-SUPPORT-STANDARD-VERSION.pdfAUTOKEYUNLOCKER-BRANDS-SUPPORT-STANDARD-VERSION.pdf
AUTOKEYUNLOCKER-BRANDS-SUPPORT-STANDARD-VERSION.pdfAutokey
 
Sql server types of joins with example.pptx
Sql server types of joins with example.pptxSql server types of joins with example.pptx
Sql server types of joins with example.pptxsameer gaikwad
 
App Builder - Hierarchical Data Apps.pptx
App Builder - Hierarchical Data Apps.pptxApp Builder - Hierarchical Data Apps.pptx
App Builder - Hierarchical Data Apps.pptxPoojitha B
 
Getting Started with Trello for Beginners.pptx
Getting Started with Trello for Beginners.pptxGetting Started with Trello for Beginners.pptx
Getting Started with Trello for Beginners.pptxmavinoikein
 
Manual de la Mezcladora SoundCraft Notepad -12Fx
Manual de la Mezcladora SoundCraft Notepad -12FxManual de la Mezcladora SoundCraft Notepad -12Fx
Manual de la Mezcladora SoundCraft Notepad -12Fxjavierdavidvelasco17
 
unit I lecture 2 - Software Engineering Ethics - Software Process.pdf
unit I lecture 2 - Software Engineering Ethics - Software Process.pdfunit I lecture 2 - Software Engineering Ethics - Software Process.pdf
unit I lecture 2 - Software Engineering Ethics - Software Process.pdfStephenTec
 
Essence of Requirements Engineering: Pragmatic Insights for 2024
Essence of Requirements Engineering: Pragmatic Insights for 2024Essence of Requirements Engineering: Pragmatic Insights for 2024
Essence of Requirements Engineering: Pragmatic Insights for 2024Asher Sterkin
 
unit I lecture 3 - Software Process Models.pdf
unit I lecture 3 - Software Process Models.pdfunit I lecture 3 - Software Process Models.pdf
unit I lecture 3 - Software Process Models.pdfStephenTec
 
Enabling Enterprise-wide OT Data access with Matrikon Data Broker.pdf
Enabling Enterprise-wide OT Data access  with Matrikon Data Broker.pdfEnabling Enterprise-wide OT Data access  with Matrikon Data Broker.pdf
Enabling Enterprise-wide OT Data access with Matrikon Data Broker.pdfJohn Archer
 
unit I lecture 5 - Software Development Life Cycle.pdf
unit I lecture 5 - Software Development Life Cycle.pdfunit I lecture 5 - Software Development Life Cycle.pdf
unit I lecture 5 - Software Development Life Cycle.pdfStephenTec
 

Recently uploaded (20)

Industry 4.0: Building the Unified Namespace with Confluent, HiveMQ and Spark...
Industry 4.0: Building the Unified Namespace with Confluent, HiveMQ and Spark...Industry 4.0: Building the Unified Namespace with Confluent, HiveMQ and Spark...
Industry 4.0: Building the Unified Namespace with Confluent, HiveMQ and Spark...
 
Steps to Build a PWA with Odoo.pdf
Steps to Build a PWA with Odoo.pdfSteps to Build a PWA with Odoo.pdf
Steps to Build a PWA with Odoo.pdf
 
maximum subarray ppt for killing camp students
maximum subarray ppt for killing camp studentsmaximum subarray ppt for killing camp students
maximum subarray ppt for killing camp students
 
Self scaling Multi cloud nomad workloads
Self scaling Multi cloud nomad workloadsSelf scaling Multi cloud nomad workloads
Self scaling Multi cloud nomad workloads
 
Les02 Restricting and Sorting Data using SQL.ppt
Les02 Restricting and Sorting Data using SQL.pptLes02 Restricting and Sorting Data using SQL.ppt
Les02 Restricting and Sorting Data using SQL.ppt
 
Open Sprintera (Where Open Source Sparks a Sprint of Possibilities)
Open Sprintera (Where Open Source Sparks a Sprint of Possibilities)Open Sprintera (Where Open Source Sparks a Sprint of Possibilities)
Open Sprintera (Where Open Source Sparks a Sprint of Possibilities)
 
100 TOOLS TO MEASURE AND ANALYSE YOUR DIGITAL MARKETING EFFORTS
100 TOOLS TO MEASURE AND ANALYSE YOUR DIGITAL MARKETING EFFORTS100 TOOLS TO MEASURE AND ANALYSE YOUR DIGITAL MARKETING EFFORTS
100 TOOLS TO MEASURE AND ANALYSE YOUR DIGITAL MARKETING EFFORTS
 
India's_Generative_AI_Startup_Landscape_Report_2023_Inc42 (1).pdf
India's_Generative_AI_Startup_Landscape_Report_2023_Inc42 (1).pdfIndia's_Generative_AI_Startup_Landscape_Report_2023_Inc42 (1).pdf
India's_Generative_AI_Startup_Landscape_Report_2023_Inc42 (1).pdf
 
unit 1 lecture 1 - Introduction - Software Engineering Myths.pdf
unit 1 lecture 1 - Introduction - Software Engineering Myths.pdfunit 1 lecture 1 - Introduction - Software Engineering Myths.pdf
unit 1 lecture 1 - Introduction - Software Engineering Myths.pdf
 
Embracing Change - The Impact of Generative AI on Strategic Portfolio Management
Embracing Change - The Impact of Generative AI on Strategic Portfolio ManagementEmbracing Change - The Impact of Generative AI on Strategic Portfolio Management
Embracing Change - The Impact of Generative AI on Strategic Portfolio Management
 
AUTOKEYUNLOCKER-BRANDS-SUPPORT-STANDARD-VERSION.pdf
AUTOKEYUNLOCKER-BRANDS-SUPPORT-STANDARD-VERSION.pdfAUTOKEYUNLOCKER-BRANDS-SUPPORT-STANDARD-VERSION.pdf
AUTOKEYUNLOCKER-BRANDS-SUPPORT-STANDARD-VERSION.pdf
 
Sql server types of joins with example.pptx
Sql server types of joins with example.pptxSql server types of joins with example.pptx
Sql server types of joins with example.pptx
 
App Builder - Hierarchical Data Apps.pptx
App Builder - Hierarchical Data Apps.pptxApp Builder - Hierarchical Data Apps.pptx
App Builder - Hierarchical Data Apps.pptx
 
Getting Started with Trello for Beginners.pptx
Getting Started with Trello for Beginners.pptxGetting Started with Trello for Beginners.pptx
Getting Started with Trello for Beginners.pptx
 
Manual de la Mezcladora SoundCraft Notepad -12Fx
Manual de la Mezcladora SoundCraft Notepad -12FxManual de la Mezcladora SoundCraft Notepad -12Fx
Manual de la Mezcladora SoundCraft Notepad -12Fx
 
unit I lecture 2 - Software Engineering Ethics - Software Process.pdf
unit I lecture 2 - Software Engineering Ethics - Software Process.pdfunit I lecture 2 - Software Engineering Ethics - Software Process.pdf
unit I lecture 2 - Software Engineering Ethics - Software Process.pdf
 
Essence of Requirements Engineering: Pragmatic Insights for 2024
Essence of Requirements Engineering: Pragmatic Insights for 2024Essence of Requirements Engineering: Pragmatic Insights for 2024
Essence of Requirements Engineering: Pragmatic Insights for 2024
 
unit I lecture 3 - Software Process Models.pdf
unit I lecture 3 - Software Process Models.pdfunit I lecture 3 - Software Process Models.pdf
unit I lecture 3 - Software Process Models.pdf
 
Enabling Enterprise-wide OT Data access with Matrikon Data Broker.pdf
Enabling Enterprise-wide OT Data access  with Matrikon Data Broker.pdfEnabling Enterprise-wide OT Data access  with Matrikon Data Broker.pdf
Enabling Enterprise-wide OT Data access with Matrikon Data Broker.pdf
 
unit I lecture 5 - Software Development Life Cycle.pdf
unit I lecture 5 - Software Development Life Cycle.pdfunit I lecture 5 - Software Development Life Cycle.pdf
unit I lecture 5 - Software Development Life Cycle.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

Editor's Notes

  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