[Go to site: main page, start]

0% found this document useful (0 votes)
28 views4 pages

.NET Programming Overview and Concepts

The document provides an overview of key .NET concepts including the Common Type System, Common Language Specification, Common Intermediate Language, and assemblies. It discusses features of C# 10 like record structs and global using directives. It also covers topics like the role of the just-in-time compiler in compiling CIL to platform-specific instructions, distinguishing between assemblies, namespaces and types, and referencing external assemblies.

Uploaded by

Fernando Torres
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
28 views4 pages

.NET Programming Overview and Concepts

The document provides an overview of key .NET concepts including the Common Type System, Common Language Specification, Common Intermediate Language, and assemblies. It discusses features of C# 10 like record structs and global using directives. It also covers topics like the role of the just-in-time compiler in compiling CIL to platform-specific instructions, distinguishing between assemblies, namespaces and types, and referencing external assemblies.

Uploaded by

Fernando Torres
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

Chapter 01

* .NET Runtime

* Common Type System

Define all posible types in .NET

5 Categories of Types

- Classes

- Structures

For each value type, the common language runtime supplies a


corresponding
boxed type which is a class that has the same state and behavior as the
value type.

- Enumerations

- Interfaces

- Delegates

* Common Language System

* .NET Standar

.NET Standard is a specification that defines the


availability of .NET APIs and base class
libraries that must be available in each implementation

* C# 10

Record structs

Global using directives and global implicit using directives

* Managed vs Unmanaged code

Unmanaged code can still be accessed from a C# program, but it then locks you
into a specific development and deployment target.

* Getting an overview of .NET Assemblies

Regardless of which .NET language you choose to program with, understand that
despite .NET binaries taking the same file extension as unmanaged Windows binaries
(*.dll), they have absolutely no internal similarities. Specifically, .NET binaries
do not contain platform-specific instructions but rather platform- agnostic
Intermediate Language (IL) and type metadata

First, unlike .NET Framework assemblies that can be either a *.dll or *.exe, .NET
projects are always compiled to a file with a .dll extension, even if the project
is an executable. Executable .NET assemblies
are executed with the command dotnet <assembly name>.dll. New in .NET Core 3.0 (and
later), the [Link] command is copied to the build directory and renamed to
<assembly name>.exe. Running this command automatically calls the dotnet <assembly
name>.dll file, executing the equivalent of dotnet <assembly name>.dll. The *.exe
with your project name isn’t actually your project’s code; it is a convenient
shortcut to running your application.

Finally, in addition to CIL and type metadata, assemblies themselves are also
described using metadata, which is officially termed a manifest. The manifest
contains information about the current version of the assembly, culture information

* The Role of the common intermediate language

* Compiling CIL to Platform-Specific Instructions

CIL code must be compiled on the fly before use. The entity that compiles CIL code
into meaningful CPU instructions is a JIT compiler, which sometimes goes by the
friendly name of jitter. The .NET runtime environment leverages a JIT compiler for
each CPU targeting the runtime, each optimized for the underlying platform.

Furthermore, as a given jitter compiles CIL instructions into corresponding machine


code, it will cache the results in memory in a manner suited to the target
operating system. In this way, if a call is made to a method named PrintDocument(),
the CIL instructions are compiled into platform-specific instructions on the first
invocation and retained in memory for later use. Therefore, the next time
PrintDocument() is called, there is no need to recompile the CIL.

* CTS Type Members

Now that you have previewed each of the types formalized by the CTS, realize that
most types take any number of members. Formally speaking, a type member is
constrained by the set {constructor, finalizer, static constructor, nested type,
operator, method, property, indexer, field, read-only field, constant, event}.

The CTS defines various adornments that may be associated with a given member. For
example, each member has a given visibility trait (e.g., public, private,
protected). Some members may be declared as abstract (to enforce a polymorphic
behavior on derived types) as well as virtual (to define a canned, but overridable,
implementation). Also, most members may be configured as static (bound at the class
level) or instance (bound at the object level).

TS type defined in an assembly named [Link]

The CLS is ultimately a set of rules that compiler builders must conform to if they
intend their products to function seamlessly within the .NET universe

Rule 1: CLS rules apply only to those parts of a type that are exposed outside the
defining assembly.

// Tell the C# compiler to check for CLS compliance.


[assembly: CLSCompliant(true)]

* .NET Runtime

* Distinguishing Between Assemlbly , Namespace and Type

- using System;

While defining a type using the fully qualified name provides greater readability,
I think you’d agree that the C# using keyword reduces keystrokes. In this text, we
will avoid the use of fully qualified names (unless there is a definite ambiguity
to be resolved) and opt for the simplified approach of the C# using keyword.
However, always remember that the using keyword is simply a shorthand notation for
specifying a type’s fully qualified name, and either approach results in the same
underlying CIL (given that CIL code always uses fully qualified names) and has no
effect on performance or the size of the assembly.

* Global Using statements

As you build more complex C# applications, you will most likely have namespaces
repeated in multiple files. Introduced in C# 10, namespaces can be referenced
globally, and then be available in every file in the project automatically. Simply
add the global keyword in front of your using statements, like this:
global using System;

<ItemGroup>
<Using Include=”[Link]” />
<Using Include=”[Link]” />
<Using Include=”[Link]” />
<Using Include=”[Link]” />
</ItemGroup>

* Implicit Global Using statements

Another new feature included with .NET 6/C# 10 are implicit global using
statements. The implicit global using statements supplied by .NET 6 varies based on
the type of application you are building.

* File Scoped Namespaces

Also new in C# 10, file-scoped namespaces remove the need to wrap your code in
braces when placing
it in a custom namespace. Take the following example of the Calculator class,
contained in the CalculatorExamples namespace. Prior to C# 10, to place a class in
a namespace required the namespace declaration, an opening curly brace, the code
(Calculator), and then a closing curly brace. In the example, the extra code is in
bold:
namespace CalculatorExamples
{
class Calculator()
{
...
}
}
As your code becomes more complex, this can add a lot of extra code and
indentation. With file scoped namespaces, the following code achieves the same
effect:
namespace CalculatorExamples
class Calculator()
{
...
}

* Referencing Externals Assemblies

Prior versions of the .NET Framework used a common installation location for
framework libraries known as the Global Assembly Cache (GAC). Instead of having a
single installation location, .NET does not use the GAC. Instead, each version
(including minor releases) is installed in its own location (by version) on the
computer

For an assembly to have access to another assembly that you are building (or
someone built for you), you need to add a reference from your assembly to the other
assembly and have physical access to the other assembly. Depending on the
development tool you are using to build your .NET applications, you will have
various ways to inform the compiler which assemblies you want to include during the
compilation cycle.

Common questions

Powered by AI

C# 10 introduced significant innovations to streamline code and improve management of namespaces and directives. Global using directives allow namespaces to be referenced globally, making them available automatically in every file within a project by using the `global` keyword before `using` statements. This reduces redundancy and simplifies project setup. Additionally, file-scoped namespaces eliminate the need for enclosing code blocks within curly braces for namespace declarations. Rather, a namespace can be declared straightforwardly, reducing indentation and enhancing code readability. These features help in creating cleaner and more maintainable code .

File-scoped namespaces in C# 10 simplify code organization by removing the need for enclosing code within curly braces when placing it in a namespace. This change reduces unnecessary indentation and code clutter in projects, especially in larger codebases where namespaces are prevalent. In previous versions, developers had to use explicit braces to define the scope of a namespace, leading to additional lines of boilerplate code. File-scoped namespaces reduce this overhead, allowing developers to write cleaner code and focus more on the logic without being distracted by structural decorations .

The Common Type System (CTS) in .NET defines various categories of types, which include classes, structures, enumerations, interfaces, and delegates. Value types, such as structures and enumerations, have special treatment as the runtime provides corresponding boxed types, which are classes that encapsulate the state and behavior of these value types. This boxing allows value types to be used as objects, permitting them to be stored on the heap unlike their typical storage on the stack, and enabling operations that are standard for reference types .

The Common Language Specification (CLS) is a key component of the .NET ecosystem designed to ensure language interoperability. It establishes a set of rules and standards that compiler builders must adhere to for their languages to function seamlessly within the .NET framework. The importance of the CLS lies in its role in defining standardized features of .NET languages that can be used across different languages without conflict. CLS compliance ensures that public interfaces are accessible by all .NET languages, promoting broader compatibility and reducing issues related to language-specific features .

With .NET Core and later versions, the compilation and execution processes have evolved, primarily shifting from the traditional .exe files to using .dll files exclusively. Every .NET project, including executables, compiles to a .dll file, which is executed using the command `dotnet <assembly name>.dll`. From .NET Core 3.0, a convenience feature was introduced where a renamed version of dotnet.exe is used as a shortcut for running the application, but it merely redirects to execute the corresponding .dll file. This flexibility ensures a platform-agnostic deployment by maintaining Intermediate Language (IL) and type metadata in the assemblies, making them suitable for cross-platform use .

Implicit global using statements are a feature introduced in .NET 6 and C# 10 designed to simplify project setup by automatically including frequently used namespaces, thus saving developers from adding repetitive using statements in each file. The specific set of implicit global using directives depends on the type of application being created, catering to common usage patterns. This feature streamlines the development process, reduces boilerplate code, and helps developers focus more on actual application logic, leading to cleaner and more readable code bases .

.NET transitioned away from using the Global Assembly Cache (GAC) to manage its assemblies, favoring a version-based directory approach. This change facilitates more granular control over assembly versions and their dependencies without a centralized location, thus eliminating potential conflicts between different versions of assemblies used by various applications. Instead, assemblies are referenced by adding specific directory paths during build processes, ensuring developers can explicitly control dependencies and enhance modularity. This shift aligns with the focus on versioning and deployment flexibility across diverse environments introduced with .NET Core and beyond .

The Just-In-Time (JIT) compiler plays a crucial role in the .NET runtime environment by compiling Common Intermediate Language (CIL) code into platform-specific instructions on the fly. This compilation is done just before the execution of the code. When a method, such as PrintDocument(), is invoked for the first time, its CIL instructions are compiled into machine code, which is stored in memory for future calls, eliminating the need for recompilation. This makes subsequent executions faster as the platform-specific machine code is reused .

Managed code is executed under the control of the .NET runtime, which provides services such as garbage collection, exception handling, and type safety. In contrast, unmanaged code is executed directly by the operating system, allowing for potentially improved performance but requiring developers to handle memory management and security explicitly. For C# developers, the use of unmanaged code can lead to increased complexity and commitment to specific development environments, as managed code abstracts these details away. Using unmanaged code necessitates careful handling, such as invoking platform-specific APIs, which can reduce the portability of applications across different .NET implementations and platforms .

Metadata and manifests are intrinsic to the structure of .NET assemblies, providing essential information about the code and its execution environment. Metadata includes details about the types, members, and references within an assembly, allowing the .NET runtime to understand dependencies, enforce security, and enable services like reflection. The manifest is a specific part of the metadata that describes the assembly itself, including its version, culture settings, and identity. It ensures that assemblies are correctly loaded and executed in the runtime environment, enabling versioning and aiding in dependency resolution .

You might also like