Overview of C# as a Language
With the introduction of modern day programming practices, it is evident that developers are looking for more advanced constructs to help them to deliver the best software in the most effective way. Languages that evolve on top of frameworks are built to enhance the capabilities of the developers in a way that allows them to quickly build their code with less complexity so that the code is maintainable, yet readable.
There are many high level object oriented programming languages available on the market, C# is not new in the programming world and has existed for over a decade, but with the dynamic progress of the language itself creating so many newe constructs, it has already oriented, type safe, general purpose language that is built on top of the .NET framework that was developed by Microsoft and approved by the European Computer Manufacturers Association (ECMA) and the International Standarts Organization (ISO). It is built to run on the Common Language Infrastructure and can interact with any other languages that are built based on the same architecture. Inspired by C++, the language is rich in delivering the best of breed applications without handling too many complexities in code.
Evolution Of C#
C# has been one of the most dynamic languages in recent times, this language is open source, some of the major enhancements that have been put forward for the language include Generics, LINQ, Dynamics, and the async/await pattern. In the next image, we can see how the language has evolved.
Managed Code: The phrase came into beign after Microsoft declared the .NET framework, any code running in a managed environment is handled by Common Language Runtime (CLR).
Generics: Is a concept that was introduced with C# 2.0 and allow template type definition and type parameters, Generics allow the programmer to define types with opened-ended type parameters that dramatically changed the way that the programmers write code. The type-safety with dynamic typed generic templates improves readability, reusability, and code performance.
LINQ: Language Integrated Query, is a new construct of queries that can be run over structures. LINQ is very new to the programming world and gives us a glimpse of functional programming on top of object oriented general programming structure. LINQ also introduced a bunch of new interfaces in the form of the IQueryable interface, which introduced a number of libraries that can interact with the external world using LINQ. LINQ was boosted with the introduction of Lambda expressions and expression trees.
Dynamics: The dynamic programming capability helps the developer to defer the programming calls to runtime. There is a specific syntactic sugar that was introduced in the language that compiles the dynamic code on the same runtime. The version also puts forward a number of new interfaces and classes that enhace its language capabilities.
Async/await: With any language, threading or asynchronous programming is a pain. When dealing with asynchrony, the programmers have to come across many complexities that reduce the readability and maintainability of the code, with the async/await feature, programming in a asynchronous way is as simple as synchronous programming. The programming has been simplified, with all of the complexities handled by the compiler and the framework internally.
Compiler as a service: Microsoft has been working on how some parts of the source code of the compiler can be opened up to the world. Consequently, as a programmer, you are capable of querying the compiler on some of its internal work principles. C# 6.0 introduced a number of libraries that enable the developer to get an insight into the compiler, the binder, the syntax tree of the program, and so on.
Exception filters: Exception filters are newly introduced and give a program the capability to filter out certain exception types. The exception filters, being a CLR construct, have been hidden in the language throughout its lifetime, but were finally introduced with C# 6.0.
C# 8 and beyond: With C# being the most dynamic language in the market, it is constantly improving. With the newer features, such as nullable reference types, async streams, ranges and indices, interface members, and many other features that came with the latest version of C#, they have enhanced the basic features and helped programmers to take advantage of these new constructs, hence making their lives easier.
Architecture of .NET
.NET framework is still well built and makes sure to make it tiered, moduler, and hierarchical. Each tier provides specific functionalities to the user some in terms of security and some in terms of language capabilities. The tiers produce a layer of abstraction to the end users and hide most of the complexities of the native operating system as much as possible. The .NET framework is partitioned into modules, with each of them having their own distinct responsibilities. The higher tiers request specific capabilities from the lower tiers and hence it is hierarchical. In the next image shows a diagram of the .NET architecture.
On its lowest level, it is the operating system that interacts with the kernel APIs that are present in the operating system. The Common Language Infrastructure connects with the Common Language Runtime, which provides services that monitor each code execution and managed memory, handles exceptions, and ensures that the application behaves as intended. Another important goal of the infrastructure is language inter-operability. The common language runtime is yet again abstracted with the .NET class libraries. This layer holds the binaries that the language is built on, and all of the compilers built on top of the libraries provide the same compiled code so that the CLR can understand the code and interact easily with one another.
Common Language Runtime: The CLR provides an interfacing between the underlying unmanaged infrastructure with the managed environment. This provides all of the basic functionalities of the managed environment in the form of garbage collection, security, and interoperability. The CLR is formed with the just-in-time compiler, which compiles the assembly code that’s produced with the specific compilers to the native calls. CLR is the most important portion of the .NET architecture.
Common Type System: Is a layer of abstraction between the language and the framework, it is evident that each of the language literals are mapped to specific CLR types. It is always preferred to use language types since the compiler takes care of the mapping of types. The CTS system is built as a hierarchy of types with System.Object at its apex. The Common Type System (CTS) is divided into two kinds, one of which is value types, which are primitives that are derived from System.ValueTypes, while anything other than that is a reference type. The value types are treated differently to the reference types. This is because while allocation of memory value types are created on a thread stack during execution, reference types are always created on the heap.
.NET framework class libraries: The framework class library lies in-between the language and the CLR, and therefore any type that’s present in the framework is exposed to the language you code. The .NET framework is formed with a good number of classes and structures, exposing never-ending functionalities that you, as a programmer, can benefit from. The class libraries are stored in the form of binaries that can be referenced directly from your program code.
Just in time compiler: .NET languages are compiled twice. During the first form of compilation, the high level language is converted into a Microsoft Intermediate Language (MSIL), which can be understood by the CLR, while the MSIL is again compiled during runtime when the program is executed. The JIT works inside the program runtime and periodically compiles the code that is expected to be required during execution.