1 Corinthians 12:20 (ESV)
“As it is, there are many parts, yet one body.”
*** Information is attributed, in part, to: “Programming C# 12 by Ian Griffiths (O’Reilly). Copyright 2024 by Ian Griffiths, 978-1-098-15836-1.”
Compilers: Historically
Historically, a compiler would process source code to produce an output that a computer’s central processor could execute directly. The computer’s processor understands specific machine code / native code, so historically, a compiler would produce an output that translated source code into a CPU’s unique machine code.
While C# can still be compiled into machine code, C# today, use’s a managed code model.
Managed Code Model
Managed code differs by having the compiler produce an intermediate language (IL), instead of CPU-specific machine code.
This intermediate language is a form of binary code that is typically (but not always) produced at runtime.
WHY USE MANAGED CODE?
The managed model provides several benefits that the historical model struggles to fulfill.
(1) The compiler’s output format is NOT tied to a single CPU architecture; therefore, multiple versions do not need to be built for x86 and x64 [32-bit & 64-bit] architecture.
The .NET managed code model allows a component to be built that would run on completely different architectures such as ARM, INTEL or AMD x86/x64.
The .NET managed code model allows you to build just one version of the code, as long as a suitable runtime is available.
(2) Improvements to the CLR [Common Language Runtime] benefit all .NET languages.
For instance, historically the CLR did not utilize vector processing extensions. Now, code running the current versions of .NET will benefit from the update that includes vector processing extensions.
Ubiquitous means “existing or being everywhere at the same time.”
(3) Managed code utilizes ubiquitous type information which is utilized by .NET runtime to enable specific features.
(3a) Automatic Serialization Services
In Automatic Serialization Services, objects are converted into binary/textual representations of their state, and those binary/textual representations can later be turned back into objects. This can even be done on a different machine. The binary/textual representations are considered to be complete & accurate descriptions of the object’s structure.
(3b) Unit Test Frameworks can inspect code in a test project & discover the unit tests the code contains.
(4) The exact moment at which the CLR generates executable machine code can be switched.
(4a) The default is just-in-time (JIT) compilation. In JIT, the machine code is generated the first time it runs, as the function is needed.
(4b) An optional runtime implementation called Mono, allows the Intermediate Language to never need to be converted to the machine language.
(4c) Another runtime option is to precompile code alongside the intermediate language creating an ahead-of-time (AOT) compilation that CAN improve an program’s start-up time.
(4cc) An extreme option is Native AOT. Applications built with Native AOT contain only native code. Runtime features like garbage collecting & runtime library components are included in the output, allowing the application to be self-contained. Writing a program in Native AOT, can seriously lower startup time.
However, not all applications will benefit from Native AOT, as they require aspects of the .NET library that need the just-in-time (JIT) compilation to generate new code at runtime.
(5) Language Integrated Query – LINQ
LINQ allows database access to integrate well with the C# programming language. The design team of C# added in additional support for functional programming idioms, anonymous types, the creation of new methods to existing types without using inheritance, and query syntax.
Collectively, these techniques allow C# to access databases more effectively.
Leave a Reply