Lowering in C# and Understanding Records with Lowering

3 min readOct 26, 2022

.Net Compiler Roslyn uses the Concept of Lowering to convert high level complex programming semantic features to Simpler low level functionalities. Like for loop to while , async await to State Machine and record type to Class and so on

Where Lowering Stands in Compilation Process

Roslyn compiler converts all our Managed Codes to unmanaged code which we can run on the machine to get results. While converting it to machine understandable code, it needs to go through the process to convert high level semantic syntax to low level features. Once we understand the compiled files we will see the difference between them. For example, while working with the Task Parallel library, we will work with high level C# features using keywords async await Task but we never have to deal with StateMachine. Roslyn uses Async Rewriter to convert all of our code into low level language. We can analyze those processes in roslyn code. Please verify below link

We can use Sharpelab to view the decompiled files, once decompile the code, we can see the difference between them.

Lets verify a foreach loop and how it is converting while compiling.

While compiling the code it is going through the process of foreach rewrite

we can verify the whole process in the above class, Roslyn repo has great documentation about each method and what is the use of it. If you need additional details please review the code and documentation.

When we write a program to loop items, machines will not understand the concept of loop. The machine will use a lot of goto statements to process the code. during the compilation process all the loops are converts to while loop and converted to machine understandable code. once we decompile them we will understand the process and how it is processing the loop. but at a high level we will use foreach, which will make as a developer our life easier while writing code. Compilers will take care of all the hard work to convert them.

Why this is, important to understand the low level functionality as a programmer, because it will give use better scope while writing the code, rather misusing the high level features.

Understanding C# Records with Lowering

Record in C# is a Class or Struct that provides additional functionalities which are helpful while working with data models. the major two feature of records are immutability and value equality.

Declaring the record in C#:

we have new keyword in C# as record, using this keyword, we can create a record type in C#. With constructor initialization syntax, it will create all the properties with getter and init accessors.

While creating the record under the hood, it is creating the class with some additional functionalities such as Implementing with IEquatable interface for value equality functionality and PrintMembers method to give object property while using ToString method. If we want to gain those all functionality all functionalities in class that comes out of the box for records. We can always override those default behaviors of records with our own implementations.

Features of Record:

Value Equality:

When we work with Classes, To compare two classes are the same with same data we need to implement our own functionality to compare them because it will compare classes as reference objects. But with records it will compare as value objects because of built in implantation of equality check. if we want to compare reference of it we can use ReferenceEquals to compare the addresses of the objects.

Non-destructive mutation:

Records come with mutation functionality by default, you can create setter for the properties to override it. With records it is easy to clone an object using with keyword. When we clone an object using with keyword we can have all the object properties with values or we can override the values without alerting the object.

Record Structs:

We can create Record struct types. All the features of the record will applies to struct type as well.

public record struct RecordStruct(int Id);

Thanks for viewing.