---
title: C-Sharp Essential Training 1 - Types and Control Flow
kind: note
description: Link Course notes from LinkedIn Learning. Explore the essentials What you should know C# compiles to MSIL All .NET languages compile to Microsoft Intermediate Language (MSIL), also known as "managed…
words: 854
readingMinutes: 4
created: '2024-06-12T18:20:49+02:00'
updated: '2026-06-29T11:03:43+02:00'
website: https://www.linkedin.com/learning/c-sharp-essential-training-1-types-and-control-flow/
---
## Link

<https://www.linkedin.com/learning/c-sharp-essential-training-1-types-and-control-flow/>

Course notes from <span class="dead-link">LinkedIn</span> [Learning](https://www.linkedin.com/learning/).
## Explore the essentials
## What you should know
## C# compiles to MSIL
- All [.NET](/notes/dot-net) languages compile to [Microsoft](/notes/microsoft) Intermediate Language (MSIL), also known as "managed code".
- Therefore the language can evolve independent of the runtime (i.e. developers can benefit from new constructs in [C#](/notes/c-sharp), while the compiled code stays compatible with the already installed runtime).
- .NET 6 was released in the fall of 2021.
## .NET runtime is responsible for running MSIL
- The runtime can be installed separately from the SDK, similar to how <span class="dead-link">Java</span> can be installed as either the JRE or JDK.
- More recent versions of the runtime allow it to be deployed together with the application, not requiring a system-wide installation as earlier.
- Thus applications targeting different runtime versions can co-exist on the same machine.
## The base class library
## NuGet packages
## Compiling C# to a library or executable
- The command-line compiler is called `csc.exe`.
## Understanding classes, structs, and records
- Some compiler options ("flags") can be set in the `*.csproj` file.
- [C# language versioning](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/configure-language-version)
- Starting in .NET 6, reference types (e.g. objects, including strings) are not nullable by default for new projects.
- Any type (reference or value) can be allowed to be nullable by declaring it with a question mark, e.g.:
	```csharp
	string? name;
	```
- All implicitly typed local variables (declared using `var`) are also nullable.
- `class`es are reference types, `struct`s are value types.
- C# 9 introduces `record`s, which are intended to be immutable, e.g. for data to pass around between services.
- C# 10 introduces `record struct`s, which have the behaviors of value types as well as records.
	- `record`s can be written as `record class`, to differentiate them from `record struct`s (even though the latter were introduced later).
- Value types can implement interfaces, but not inherit from a base class.
## Defining constructors
- In Visual Studio, `ctor` is a keyboard shortcut to scaffold a constructor (stub).
- The constructor method has the same name as the class.
- A constructor can invoke the constructor of its base class like this:
	```csharp
	public ClassA() : base("param1") { }
	```
- Since C# 6, you can prefix a string with a `$` sign to have embedded variables (within `{}`) interpolated.
- In a method signature, default values can be provided for arguments, making them optional.
## Object initialization
- Instead of using a constructor to initialize (create) an object, we can use object initialization to set any property we want. Notice the curly braces instead of the parentheses:
	```csharp
	Employee e = new Employee{
	  FirstName = "Claus",
	  LastName = "Conrad";
	};
	```
- Object initialization (as shown above) is shorthand for calling the default constructor (without arguments) and then setting the properties.
- It can also be combined with another constructor, e.g.
	```csharp
	Employee e = new Employee("Claus"){
	  LastName = "Conrad";
	};
	```
- "Roslyn" is the name of a specific C# compiler that is itself implemented in C# (similar to how PyPy is a [Python](/notes/python) interpreter written in Python).
- Any constructor for a `struct` needs to set a value for all properties (since a `struct` is a value type).
## Initialize only properties
- A property declared with `init` instead of `set` can _only_ be set by a constructor or using object initialization:
	```csharp
	public byte CustomerLevel { get; init; }
	```
- This is often used on `record` types to make their values immutable.
- The access of `get` and `set` can be controlled, e.g.
	```csharp
	public int YearsOld { get; private set; }
	```
## Cloning and copying objects
- A reference type (such as an instance of a `class`, a.k.a. an object) can have multiple variables pointing at it.
	- By default, when a (reference type) variable is passed to a method and the method assigns something else to the variable, that change does not persist after the method returns.
	- This behavior can be changed by prefixing the variable with `ref` - both in the method definition (signature) and when calling it (argument list). In this case, if the method changes what "object" the (reference type) variable points at, the original variable is modified, and so the change persists after the method returns.
- When a new variable is assigned a `struct` (i.e. a value type), then the value is copied, and the two variables (while they initially have the same value) can be modified independently from here on.
	- The same applies when a `struct` is passed to a method - a copy local to the method is created, and changes to it do *not* persist after the method returns.
	- This behavior can be changed by prefixing the variable with `ref` - both in the method definition (signature) and when calling it (argument list). In this case, if the method changes the "struct" (the value type), the original value is modified, and so the change persists after the method returns.
- The `with` keyword can be used to copy a `record` with modifications, e.g.
	```csharp
	public record Customer { /* ... */ }
	Customer c = new Customer{ FirstName = "Claus", LastName = "Conrad" };
	Customer c2 = c with { Lastname = "Clausen" };
	```
## Equality comparisons
- A `record` can be defined using two different syntaxes:
	- Similar to a `class`:
		```csharp
		public record RClassLike
		{
		   public int Id { get; set; }
		}
		```
	- Shorthand syntax:
		```csharp
		public record RShorthand(int Id);
		```
	- In the shorthand example, this defines the `record`, its constructor and its single property at the same time. The `Id` can only be set using this constructor (or using this constructor and an object initializer, but that does not make sense here) and is read-only afterwards (i.e. this syntax is similar to using the `init` keyword).
- By default, when comparing for equality,
	- for `struct`s, the equality operator (`==`) is not defined (but the developer can implement it);
	- for `class` instances, equality means whether they point to the same object;
	- for `record`s, the framework checks whether all properties have the same value.
- When overriding/implementing the `==`/`!=` operators, one should also override/implement the `Equals()` method.
