C# 7 and .NET Core 2.0 High Performance

4.3 (3 reviews total)
By Ovais Mehboob Ahmed Khan
  • Instant online access to over 8,000+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. What's New in .NET Core 2 and C# 7?

About this book

While writing an application, performance is paramount. Performance tuning for realworld applications often involves activities geared toward fnding bottlenecks; however, this cannot solve the dreaded problem of slower code. If you want to improve the speed of your code and optimize an application's performance, then this book is for you. C# 7 and .NET Core 2.0 High Performance begins with an introduction to the new features of what?explaining how they help in improving an application's performance. Learn to identify the bottlenecks in writing programs and highlight common performance pitfalls, and learn strategies to detect and resolve these issues early. You will explore multithreading and asynchronous programming with .NET Core and learn the importance and effcient use of data structures. This is followed with memory management techniques and design guidelines to increase an application’s performance. Gradually, the book will show you the importance of microservices architecture for building highly performant applications and implementing resiliency and security in .NET Core. After reading this book, you will learn how to structure and build scalable, optimized, and robust applications in C#7 and .NET.

Publication date:
April 2018
Publisher
Packt
Pages
300
ISBN
9781788470049

 

Chapter 1. What's New in .NET Core 2 and C# 7?

.NET Core is a development platform by Microsoft that runs cross-platform and is maintained by Microsoft and the community at GitHub. It is the most emergent and popular framework in development communities due to its performance and platform portability. It targets every developer that can develop any application for any platform that includes web, cloud, mobile, embedded, and IoT scenarios.

With .NET Core, we can develop applications using C#, F#, and now VB.NET as well. However, C# is the most widely used language among developers.

In this chapter, you will learn the following topics:

  • Performance improvements in .NET Core 2.0
  • Upgrading the path from .NET Core 1.x to 2.0
  • .NET Standard 2.0
  • What comes with ASP.NET Core 2.0
  • New features in C# 7.0
 

Evolution of .NET


In early 2002, when Microsoft first introduced the .NET Framework, it targeteddevelopers who were working on classic ASP or VB 6 platforms since they didn't have any compelling framework for developing enterprise-level applications. With the release of the .NET Framework, developers had a platform to develop applications and could choose any of the languages from VB.NET, C#, and F#. Irrespective of the language chosen, the code is interoperable, and developers can create a project with VB.NET and reference it in their C# or F# project and vice versa.

The core component of .NET Framework includes Common Language Runtime (CLR), Framework Class Libraries (FCL), Base Class Libraries (BCL), and a set of application models. New features and patches have been introduced with the newer version of the .NET Framework, which comes with the new release of Windows, and developers have had to wait for a year or so to get those improvements. Every team at Microsoft worked on a different application model, and each team had to wait for the date when the new framework was released to port their fixes and improvements. Windows Forms and Web Forms were the primary application models at that time that were widely used by .NET developers.

When Web Forms was first introduced, it was a breakthrough which attracted both web developers who worked on Classic ASP and desktop application developers who worked on Visual Basic 6.0. The developer experience was appealing and provided a decent set of controls that could easily be dragged and dropped to the screen, followed to their events and properties that could be set either through the view file (.aspx) or code-behind files. Later on, Microsoft introduced the Model View Controller (MVC) application model that implemented the separation of concerns design principle, so that View, Model, and Controller are separate entities. The View is the user interface that renders the Model, where the Model represents the business entity and holds the data, and the Controller that handles the request and updates the model and injects it into the View. MVC was a breakthrough that let developers write cleaner code and bind their model with the HTML controls using model binding. With the passage of time, more features were added and the core .NET web assembly System.Web became quite big and bloated, and contained lots of packages and APIs that were not always useful in every type of application. However, with .NET, several groundbreaking changes were introduced and System.Web got split into NuGet packages that can be referenced and added individually based on requirements.

.NET Core (codename .NET vNext) was first introduced in 2014, and the following are the core benefits of using .NET Core:

Benefit

Description

Cross Platform

.NET Core can run on Windows, Linux, and macOS

Host Agnostic

.NET Core on the server side is not dependent on IIS and, with two lightweight servers, Kestrel and WebListener, it can be self-hosted as a Console application and can be also gelled with mature servers such as IIS, Apache, and others through a reverse proxy option

Modular

Ships as NuGet packages

Open Source

The entire source code is released as open source via the .NET Foundation

CLI tooling

Command line tools to create, build, and run projects from the command line

 

.NET Core is a cross-platform, open-source framework that implements .NET Standard. It provides a runtime known as .NET Core CLR, framework class libraries, which are primitive libraries known as CoreFX, and APIs that are similar to what .NET Framework has, but have a smaller footprint (lesser dependencies on other assemblies):

.NET Core provides flexible deployment options as follows:

  • Framework-Dependent Deployment (FDD): needs .NET Core SDK to be installed on the machine
  • Self-Contained Deployment (SCD): No machine-wide installation of .NET Core SDK is needed on the machine and .NET Core CLR and framework class libraries are part of the application package

Note

To install .NET Core 2.0, you can navigate to the following link https://www.microsoft.com/net/core and go through the options for installing it on Windows, Linux, MAC, and Docker.

 

New improvements in .NET Core 2.0


The most recent version of .NET Core, 2.0, comes with a number of improvements. .NET Core 2.0 is the fastest version of all times and can run on multiple platforms including various Linux distros, macOS (operating system), and Windows.

Note

Distros stands for Linux distribution (often abbreviated as distro), and it is an operating system made from a software collection, which is based upon the Linux kernel and, often, a package management system.

Performance improvements

.NET Core is more robust and performance efficient and, since it's open source, the Microsoft team with other community members are bringing more improvements.

The following are the improvements that are part of .NET Core 2.0.

RyuJIT compiler in .NET Core

RyuJIT is a next-generation JIT compiler that is a complete rewrite of the Just In Time (JIT) compiler and generates a lot more efficient native machine code. It is twice as fast as the previous 64-bit compiler and provides 30% faster compilation. Initially, it runs on only X64 architectures, but now it supports X86 as well and developers can use the RyuJIT compiler for both X64 and X86. .NET Core 2.0 uses RyuJIT for both X86 and X64 platforms.

Profile guided optimization

Profile-guided optimization (PGO) is a compilation technology used by C++ compiler to generate optimized code. It applies to the internal native compiled components of the runtime and JIT. It performs compilation in two steps, which are as follows:

  1. It records the information about code execution.
  2. From this information, it generates better code.

The following diagram depicts the life cycle of how the code is compiled:

In .NET Core 1.1, Microsoft already released the PGO for Windows X64 architecture, but in .NET Core 2.0, this has been added for both Windows X64 and X86 architectures. Also, as per observatory results, it was noted that the actual startup time is mostly taken by coreclr.dll and clrjit.dll for Windows. Alternatively, on Linux, there are libcoreclr.so and libclrjit.so, respectively.

Comparing RyuJIT with the old JIT compiler known as JIT32, RyuJIT is more efficient in code generation. The startup time of the JIT32 was faster than the RyuJIT; however, the code is not efficient. To overcome the initial startup time taken by the RyuJIT compiler, Microsoft used PGO, which brought the performance closer to JIT32 performance and achieved both efficient code and performance on startup.

For Linux, the compiler toolchain is different for each distro, and Microsoft is working on a separate Linux version of .NET that uses the PGO optimizations applicable to all distros.

Simplified packaging

With .NET Core, we can add libraries to our project from NuGet. All framework and third-party libraries can be added as NuGet packages. With a large sized application that refers many libraries, adding each library one by one is a cumbersome process. .NET Core 2.0 has simplified the packaging mechanism and introduced meta-packages that can be added as one single package that contains all the assemblies that are linked to it.

For example, if you wanted to work on ASP.NET Core in .NET Core 2.0, you just have to add one single package, Microsoft.AspNetCore.All, using NuGet.

The following is the command that will install this package into your project:

Install-Package Microsoft.AspNetCore.All -Version 2.0.0
 

Upgrading path from .NET Core 1.x to 2.0


.NET Core 2.0 comes with lots of improvements, and this is the primary reason people wanted to migrate their existing .NET Core applications from 1.x to 2.0. However, there is a checklist which we will go through in this topic to ensure smooth migration.

1. Install .NET Core 2.0

First of all, install the .NET Core 2.0 SDK on your machine. It will install the latest assemblies to your machine, which will help you to execute further steps.

2. Upgrade TargetFramework

This is the most important step, and this is where the different versions need to be upgraded in the .NET Core project file. Since we know that, with the .csproj type, we don't have project.json, to modify the framework and other dependencies, we can edit the existing project using any Visual Studio editor and modify the XML.

The XML Node that needs to be changed is the TargetFramework. For .NET Core 2.0, we have to change the TargetFramework moniker to netcoreapp2.0, which is shown as follows:

<TargetFramework>netcoreapp2.0</TargetFramework>

Next, you can start building the project which will upgrade the .NET Core dependencies to 2.0. However, there is a chance of a few of them still referencing the older version, and upgrading those dependencies needs to be done explicitly using NuGet package manager.

3. Update .NET Core SDK version

If you have global.json added to your project, you have to update the SDK version to 2.0.0, which is shown as follows:

{ 
  "sdk": { 
    "version": "2.0.0" 
  } 
} 

4. Update .NET Core CLI

.NET Core CLI is also an important section in your .NET Core project file. When migrating, you have to upgrade the version of DotNetCliToolReference to 2.0.0, which is shown as follows:

<ItemGroup> 
  <DotNetCliToolReference Include=
  "Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" /> 
</ItemGroup> 

There might be more tools added depending on whether you are using Entity Framework Core, User Secrets, and others. You have to update their versions.

Changes in ASP.NET Core Identity

There have been some more improvements and changes to the ASP.NET Core Identity model. Some of the classes are renamed and you can find them at: http://docs.microsoft.com/en-us/aspnet/core/migration.

 

Exploring .NET Core CLI and New Project Templates


Command Line Interface (CLI) is a very popular tool is almost all popular frameworks like Yeoman Generator, Angular, and others. It lends developers access to execute commands to create, build, and run projects, restore packages, and so on.

.NET CLI provides a toolset with a handful commands that can be executed from the command line interface to create .NET Core projects, restore dependencies, and build and run projects. Under the wire, Visual Studio 2015/2017 and Visual Studio Code even uses this tool to perform different options taken by the developers from their IDE; for example, to create a new project using .NET CLI, we can run the following command:

dotnet new

It will list down the available templates and the short name that can be used while creating the project.

Here is the screenshot containing the list of project templates that can be used to create/scaffold projects using .NET Core CLI:

And by running the following command, a new ASP.NET Core MVC application will be created:

dotnet new mvc

The following screenshot shows the provisioning of the new MVC project after running the preceding command. It creates the project in the same directory where the command is running and restores all the dependencies:

To install the .NET Core CLI toolset, there are some native installers available for Windows, Linux, and macOS. These installers can install and set up the .NET CLI tooling on your machine and developers can run the commands from the CLI.

Here is the list of commands with their descriptions that are provided in the .NET Core CLI:

Command

Description

Example

new

Creates a new project based on the template selected

dotnet new razor

restore

Restores all the dependencies defined in the project

dotnet restore

build

Builds the project

dotnet build

run

Runs the source code without any additional compile

dotnet run

publish

Packages the application files into a folder for deployment

dotnet publish

test

Used to execute unit tests

dotnet test

vstest

Executes unit tests from specified files

dotnet vstest [<TEST_FILE_NAMES>]

pack

Packs the code into a NuGet package

dotnet pack

migrate

Migrates .NET Core preview 2 to .NET Core 1.0

dotnet migrate

clean

Cleans the output of the project

dotnet clean

sln

Modifies a .NET Core solution

dotnet sln

help

Displays the list of commands available to execute through .NET CLI

dotnet help

store

Stores the specified assemblies in the runtime package store

dotnet store

 

Here are some of the project level commands that can be used to add a new NuGet package, remove an existing one, list references, and others:

Command

Description

Example

add package

Adds a package reference to the project

dotnet add package Newtonsoft.Json

remove package

Removes a package reference from the project

dotnet remove package Newtonsoft.Json

add reference

Adds a project reference to the project

dotnet add reference chapter1/proj1.csproj

remove reference

Removes the project reference from the project

dotnet remove reference chapter1/proj1.csproj

list reference

List down all the project references in the project

dotnet list reference

The following are some common Entity Framework Core commands that can be used to add migration, remove migration, update the database, and so on.

Command

Description

Example

dotnet ef migrations add

Adds a new migration

dotnet ef migrations add Initial

- Initial is the name of migration

dotnet ef migrations list

List available migrations

dotnet ef migrations list

dotnet ef migrations remove

Remove specific migration

dotnet ef migrations remove Initial

- Initial is the name of migration

dotnet ef database update

To update the database to a specified migration

dotnet ef database update Initial

- Initial is the name of migration

dotnet ef database drop

Drops the database

dotnet ef database drop

Here are some of the server level commands that can be used to delete the NuGet package from its actual source repository from the machine, add NuGet package into its actual source repository on the machine, and so on:

Command

Description

Example

nuget delete

Deletes the package from the server

dotnet nuget delete Microsoft.AspNetCore.App 2.0

nuget push

Pushes a package to the server and publishes it

dotnet nuget push foo.nupkg

nuget locals

Lists the local NuGet resources

dotnet nuget locals -l all

msbuild

Builds a project and all of its dependencies

dotnet msbuild

dotnet install script

The script to install the .NET CLI tools and the shared runtime

./dotnet-install.ps1 -Channel LTS

To run the preceding commands, we can use the tool known as dotnet from the command line and specify the actual command followed by that. When the .NET Core CLI is installed, it is set into the PATH variable in Windows OS and can be accessed from any folder. So, for example, if you are at your project root folder and wanted to restore the dependencies, you can just call the following command and it will restore all the dependencies that have been defined in your project file:

dotnet restore

The preceding command will start restoring the dependencies or project-specific tools, as defined in the project file. The restoration of tools and dependencies are done in parallel:

We can also set the path where packages can be restored by using the --packages argument. However, if this is not specified, it uses the .nuget/packages folder under the system's user folder. For example, the default NuGet folder for Windows OS is {systemdrive}:\Users\{user}\.nuget\packages and /home/{user} for Linux OS, respectively.

 

Understanding .NET Standard


In the .NET ecosystem, there are many runtimes. We have the .NET Framework, which is a full machine-wide framework installed on the Windows operating system and provides app models for Windows Presentation Foundation (WPF), Windows Forms, and ASP.NET. Then, we have .NET Core, which is targeted at cross-platform operating systems and devices and provides ASP.NET Core, Universal Windows Platform (UWP), and a Mono runtime that is targeted at Xamarin applications and developers who can use Mono runtime to develop applications on Xamarin and run on iOS, Android, and Windows OS.

The following diagram depicts how the .NET Standard Library provides an abstraction of .NET Framework, .NET Core, and Xamarin with the common building blocks:

All of these runtimes implement an interface known as .NET Standard, where .NET Standard is the specification of .NET APIs that have the implementation for each runtime. This makes your code portable across different platforms. This means the code created for one runtime can also be executed by another runtime. .NET Standard is the next generation of Portable Class Libraries (PCL) we used earlier. Just to recap, PCL is a class library that targets one or more frameworks of .NET. When creating a PCL, we can select the target frameworks where this library needs to be used, and it minimizes the assemblies and uses only those that are common to all frameworks.

The .NET Standard is not an API or executable that can be downloaded or installed. It is a specification that defines the API that each platform implements. Each runtime version implements a specific .NET Standard version. The following table shows the versions of .NET Standard each platform implements:

We can see that .NET Core 2.0 implements .NET Standard 2.0 and that .NET Framework 4.5 implements .NET Standard 1.1., so for example, if we have a class library developed on .NET Framework 4.5, this can easily be added into the .NET Core project because it implements a greater version of .NET Standard. On the other hand, if we wanted to reference the .NET Core assembly into .NET Framework 4.5, we can do so by changing the .NET Standard version to 1.1 without recompiling and building our project.

As we learned, the basic idea of .NET Standard is to share code between different runtimes, but how it differs from PCL is shown as follows:

Portable Class Library (PCL)

.NET Standard

Represents the Microsoft platform and targets a limited set of platforms

Agnostic to platform

APIs are defined by the platforms you target

Curated set of APIs

They are not linearly versioned

Linearly versioned

 

.NET Standard is also mapped to PCL, so if you have an existing PCL library that you wanted to convert to .NET Standard, you can reference the following table:

PCL Profile

.NET Standard

PCL Plaforms

7

1.1

.NET Framework 4.5, Windows 8

31

1.0

Windows 8.1, Windows Phone Silverlight 8.1

32

1.2

Windows 8.1, Windows Phone 8.1

44

1.2

.NET Framework 4.5.1, Windows 8.1

49

1.0

.NET Framework 4.5, Windows Phone Silverlight 8

78

1.0

.NET Framework 4.5, Windows 8, Windows Phone Silverlight 8

84

1.0

Windows Phone 8.1, Windows Phone Silverlight 8.1

111

1.1

.NET Framework 4.5, Windows 8, Windows Phone 8.1

151

1.2

.NET Framework 4.5.1, Windows 8.1, Windows Phone 8.1

157

1.0

Windows 8.1, Windows Phone 8.1, Windows Phone Silverlight 8.1

259

1.0

.NET Framework 4.5, Windows 8, Windows Phone 8.1, Windows Phone Silverlight 8

Considering the preceding table, if we have a PCL that targets .NET Framework 4.5.1, Windows 8.1, and Windows Phone 8.1 with the PCL profile set to 151, it can be converted to the .NET Standard library with version 1.2.

Versioning of .NET Standard

Unlike PCL, each version of .NET Standard is linearly versioned and contains the APIs for the previous versions and so on. Once the version is shipped, it is frozen and cannot be changed, and the application can easily target that version.

The following diagram is a representation of how .NET Standard is versioned. The higher the version is, the more APIs will be available, whereas the lower the version is, the more platforms will be available:

New improvements in .NET Standard 2.0

.NET Core 2.0 is targeted at .NET Standard 2.0 and provides two major benefits. This includes the increase in the number of APIs provided from the previous version and its compatibility mode, as we will discuss further in this chapter.

More APIs in .NET Standard 2.0

More APIs have been added into .NET Standard 2.0 and the number is almost double that of the previous .NET Standard, 1.0. Additionally APIs like DataSet, collections, binary serialization, XML schema, and others are now part of .NET Standard 2.0 specification. This has increased the portability of code from .NET Framework to .NET Core.

The following diagram depicts the categorical view of APIs added in each area:

Compatibility mode

Although more than 33K APIs have been added into .NET Standard 2.0, many of the NuGet packages still target .NET Framework, and moving them to .NET Standard is not possible, since their dependencies are still not targeted at .NET Standard. However, with .NET Standard 2.0, we can still add packages which show a warning but don't block adding those packages into our .NET Standard library.

Under the hood, .NET Standard 2.0 uses compatibility shim, which solves the third party library compatibility issue and makes it easy in referencing those libraries. In the CLR world, the identity of the assembly is part of the type identity. This means that when we say System.Object in .NET Framework, we are referencing [mscorlib]System.Object and with .NET Standard, we are referencing [netstandard]System.Object, so if we are referencing any assembly which is part of .NET Framework, it cannot be easily run on .NET Standard and so compatibility issues arise. To solve this problem, they have used type forwarding which provides a fake mscorlib assembly that type forwards all the types to the .NET Standard implementation.

Here is a representation of how the .NET Framework libraries can run in any of the .NET Standard implementations using the type forwarding approach:

On the other hand, if we have a .NET Framework library and we wanted to reference a .NET Standard library, it will add the netstandard fake assembly and perform type forwarding of all the types by using the .NET Framework implementation:

Note

To suppress warnings, we can add NU1701 for particular NuGet packages whose dependencies are not targeting .NET Standard.

 

Creating a .NET Standard library


To create a .NET Standard library, you can either use Visual Studio or the .NET Core CLI toolset. From Visual Studio, we can just click on the .NET Standard option as shown in the following screenshot, and select Class Library (.NET Standard).

Once the .NET Standard library is created, we can reference it to any project and change the version if needed, depending on which platform we want to reference. The version can be changed from the properties panel, as shown in the following screenshot:

 

What comes with ASP.NET Core 2.0


ASP.NET Core is one of the most powerful platforms for developing cloud-ready and enterprise web applications that run cross-platform. Microsoft has added many features with ASP.NET Core 2.0, and that includes new project templates, Razor Pages, simplified provisioning of Application Insights, connection pooling, and so on.

The following are some new improvements for ASP.NET Core 2.0.

ASP.NET Core Razor Pages

Razor syntax-based pages have been introduced in ASP.NET Core. Now, developers can develop applications and write syntax on the HTML with no controller in place. Instead, there is a code behind file where other events and logic can be handled. The backend page class is inherited from the PageModel class and its member variables and methods can be accessed using the Model object in Razor syntax. The following is a simple example that contains the GetTitle method defined in the code-behind class and used in the view page:

public class IndexModel : PageModel 
{ 
  public string GetTitle() => "Home Page"; 
}

Here is the Index.cshtml file that displays the date by calling the GetCurrentDate method:

@page 
@model IndexModel 
@{ 
  ViewData["Title"] = Model.GetTitle(); 
} 

Automatic Page and View compilation on publishing

On publishing the ASP.NET Core Razor pages project, all the views are compiled into one single assembly and the published folder size is comparatively small. In case we want view and all the .cshtml files to be generated when the publishing process takes place, we have to add an entry, which is shown as follows:

Razor support for C# 7.1

Now, we can use C# 7.1 features such as inferred tuple names, pattern matching with generics, and expressions. In order to add this support, we have to add one XML tag as follows in our project file:

<LangVersion>latest</LangVersion>

Simplified configuration for Application Insights

With ASP.NET Core 2.0, you can enable Application Insights with a single click. A user can enable Application Insights by just right clicking Project and hitting Add | Application Insights Telemetry before going through a simple wizard. This allows you to monitor the application and provides complete diagnostics information from Azure Application Insights.

We can also view the complete telemetry from the Visual Studio 2017 IDE from the Application Insights Search window and monitor trends from Application Insights Trends. Both of these windows can be opened from the View | Other Windows menu.

Pooling connections in Entity Framework Core 2.0

With the recent release of Entity Framework Core 2.0, we can pool connections by using the AddDbContextPool method in the Startup class. As we already know, in ASP.NET Core, we have to add the DbContext object using Dependency Injection (DI) in the ConfigureServices method in the Startup class, and when it is used in the controller, a new instance of the DbContext object is injected. To optimize performance, Microsoft has provided this AddDbContextPool method, which first checks for the available database context instance and injects it wherever it is needed. On the other hand, if the database context instance is not available, a new instance is created and injected.

The following code shows how AddDbContext can be added in the ConfigureServices method in the Startup class:

services.AddDbContextPool<SampleDbContext>( 
  options => options.UseSqlServer(connectionString)); 

Note

There are some more features added to Owned Types, Table splitting, Database Scalar Function mapping, and string interpolation that you can refer to from the following link: https://docs.microsoft.com/en-us/ef/core/what-is-new/.

 

New features in C# 7.0


C# is the most popular language in the .NET ecosystem and was first introduced with the .NET Framework in 2002. The current stable version of C# is 7. The following chart shows how C# 7.0 has progressed and what versions were introduced in different years:

Here are some of the new features that were introduced with C# 7.0:

  • Tuples
  • Pattern matching
  • Reference returns
  • Exceptions as expressions
  • Local functions
  • Out variables Literals
  • Async Main

Tuples

Tuples solve the problem of returning more than one value from a method. Traditionally, we can use out variables that are reference variables, and the value is changed if they are modified from the calling method. However, without parameters, there are some limitations, such as that it cannot be used with async methods and is not recommended to be used with external services.

Tuples have the following characteristics:

  • They are value types.
  • They can be converted to other Tuples.
  • Tuple elements are public and mutable.

A Tuple is represented as System.Tuple<T>, where T could be any type. The following example shows how a Tuple can be used with the method and how the values can be invoked:

static void Main(string[] args) 
{ 
  var person = GetPerson(); 
  Console.WriteLine($"ID : {person.Item1}, 
  Name : {person.Item2}, DOB : {person.Item3}");       
} 
static (int, string, DateTime) GetPerson() 
{ 
  return (1, "Mark Thompson", new DateTime(1970, 8, 11)); 
}

As you may have noticed, items are dynamically named and the first item is named Item1, the second Item2, and so on. On the other hand, we can also name the items so that the calling party should know about the value, and this can be done by adding the parameter name for each parameter in the Tuple, which is shown as follows:

static void Main(string[] args) 
{ 
  var person = GetPerson(); 
  Console.WriteLine($"ID : {person.id}, Name : {person.name}, 
  DOB : {person.dob}");  
} 
static (int id, string name, DateTime dob) GetPerson() 
{ 
  return (1, "Mark Thompson", new DateTime(1970, 8, 11)); 
} 

Note

To learn more about Tuples, please check the following link:https://docs.microsoft.com/en-us/dotnet/csharp/tuples.

Patterns

Patterns matching is the process of performing syntactical testing of the value to verify whether it matches the certain model. There are three types of patterns:

  • Constant patterns.
  • Type patterns.
  • Var patterns.

Constant pattern

A constant pattern is a simple pattern that checks for the constant value. Consider the following example: if the Person object is null, it will return and exit the body method.

The Person class is as follows:

class Person 
{ 
  public int ID { set; get; } 
  public string Name { get; set; } 
 
  public DateTime DOB { get; set; } 
} 

In the preceding code snippet, we have a Person class that contains three properties, namely ID, Name, and DOB (Date of Birth).

The following statement checks for the person object with a null constant value and returns it if the object is null:

if (person is null) return; 

Type pattern

The type pattern can be used with an object to verify whether it matches the type or suffices the expression based on the conditions specified. Suppose we need to check whether the PersonID is int; assign that ID to another variable, i, and use it in the program, otherwise return:

if (!(person.ID is int i)) return; 
 
Console.WriteLine($"Person ID is {i}"); 

We can also use multiple logical operators to evaluate more conditions, as follows:

if (!(person.ID is int i) && !(person.DOB>DateTime.Now.AddYears(-20))) return;   

The preceding statement checks whether the Person.ID is null or not and whether the person is older than 20.

Var pattern

The var pattern checks if the var is equal to some type. The following example shows how the var pattern can be used to check for the type and print the Type name:

if (person is var Person) Console.WriteLine($"It is a person object and type is {person.GetType()}"); 

Note

To learn more about patterns, you can refer to the following link: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#pattern-matching.

Reference returns

Reference returns allows a method to return an object as a reference instead of its value. We can define the reference return value by adding a ref keyword before the type in the method signature and when returning the object from the method itself.

Here is the signature of the method that allows reference returns:

public ref Person GetPersonInformation(int ID); 
 
Following is the implementation of the GetPersonInformation method that uses the ref keyword while returning the person's object.  
 
Person _person; 
public ref Person GetPersonInformation(int ID) 
{ 
  _person = CallPersonHttpService(); 
  return ref _person; 
} 

Expression bodied member extended

Expression bodied members were introduced in C# 6.0 where the syntactical expression of the method can be written in a simpler way. In C# 7.0, we can use this feature with a constructor, a destructor, an exception, and so on.

The following example shows how the constructor and destructor syntactic expressions can be simplified using expression bodied members:

public class PersonManager 
{ 
  //Member Variable 
  Person _person; 
 
  //Constructor 
  PersonManager(Person person) => _person = person; 
 
  //Destructor 
  ~PersonManager() => _person = null; 
} 

With properties, we can also simplify the syntactic expression, and the following is a basic example of how this can be written:

private String _name; 
public String Name 
{ 
  get => _name; 
  set => _name = value; 
} 

We can also use an expression bodied syntactic expression with exceptions and simplify the expression, which is shown as follows:

private String _name; 
public String Name 
{ 
  get => _name; 
  set => _name = value ?? throw new ArgumentNullException(); 
} 

In the preceding example, if the value is null, a new ArgumentNullException will be thrown.

Creating Local Functions

Functions that are created within a function are known as Local Functions. These are mainly used when defining helper functions that have to be in the scope of the function itself. The following example shows how the factorial of the number can be obtained by writing a Local Function and calling it recursively:

static void Main(string[] args) 
{ 
  Console.WriteLine(ExecuteFactorial(4));          
} 
 
static long ExecuteFactorial(int n) 
{ 
  if (n < 0) throw new ArgumentException("Must be non negative", 
  nameof(n)); 
            
  else return CheckFactorial(n); 
 
  long CheckFactorial(int x) 
  { 
    if (x == 0) return 1; 
    return x * CheckFactorial(x - 1); 
  } 
}

Out variables

With C# 7.0, we can write cleaner code when using out variables. As we know, to use out variables, we have to first declare them. With the new language enhancement, we can now just write out as a prefix and specify the name of the variable that we need that value to be assigned to.

To clarify this concept, we will first see the traditional approach, which is shown as follows:

public void GetPerson() 
{ 
  int year; 
  int month; 
  int day; 
  GetPersonDOB(out year, out month, out day); 
} 
 
public void GetPersonDOB(out int year, out int month, out int day ) 
{ 
  year = 1980; 
  month = 11; 
  day = 3; 
} 

And here with C# 7.0, we can simplify the preceding GetPerson method, which is shown as follows:

public void GetPerson() 
{ 
  GetPersonDOB(out int year, out int month, out int day); 
} 

Async Main

As we already know, in .NET Framework, the Main method is the main entry point from where the application/program is executed by the OS. For example, in ASP.NET Core, Program.cs is the main class where the Main method is defined, which creates a WebHost object, runs the Kestrel server, and loads up the HTTP pipeline as configured in the Startup class.

In the previous version of C#, the Main method had the following signatures:

public static void Main();
public static void Main(string[] args);
public static int Main();
public static int Main(string[] args);

In C# 7.0, we can use Async Main to perform asynchronous operations. The Async/Await feature was initially released in .NET Framework 4.5 in order to execute methods asynchronously. Today, many APIs provides Async/Await methods to perform asynchronous operations.

Here are some additional signatures of the Main method that have been added with C# 7.1:

public static Task Main();
public static Task Main(string[] args);
public static Task<int> Main();
public static Task<int> Main(string[] args);

Because of the preceding async signatures, we can now call async methods from the Main entry point itself and use await to perform an asynchronous operation. Here is a simple example of ASP.NET Core that calls the RunAsync method instead of Run:

public class Program
{
  public static async Task Main(string[] args)
  {
    await BuildWebHost(args).RunAsync();
  }
  public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .Build();
}

Async Main is a feature of C# 7.1, and to enable this feature in Visual Studio 2017, you can go to the project properties, click on the Advance button and set the Language version as C# latest minor version (latest), which is shown as follows:

 

Writing quality code


For every performance-efficient application, code quality plays an important role. As we already know, Visual Studio is the most popular Integrated Development Environment (IDE) for developing .NET applications, and since Roslyn (.NET Compiler SDK) exposes compiler platforms as APIs, many features have been introduced that do not only extend the capabilities of Visual Studio, but enhance the development experience.

Live Static Code analysis is one of the core features that can be used in Visual Studio in developing .NET applications which provides code analysis during development while writing code. As this feature uses the Roslyn APIs, many other third-party companies have also introduced sets of analyzers that can be used. We can also develop our own analyzer for a particular requirement, and it's not a very complicated procedure. Let's look at a quick introduction on how we can use Live Static Code analysis in our .NET Core project and how it benefits the development experience by analyzing code and giving warnings, errors, and potential fixes for them.

We can add analyzer as a NuGet package. In NuGet.org, there are many analyzers available, and once we add any analyzer into our project, it adds a new Analyzer node into the Dependencies section of the project. We can then customize rules, suppress warnings or errors, and so on.

Let's add a new analyzer from Visual Studio in our .NET Core project. If you don't know which analyzer you want to add, you can just type analyzers in the NuGet Package manager window and it will list all the analyzers for you. We will just add the Microsoft.CodeQuality.Analyzers analyzer, which contains some decent rules:

Once the selected Analyzer is added, a new Analyzers node is added into our project:

In the preceding picture, we can see that three nodes have been added to the Analyzers node, and to see/manage the rules, we can expand the subnodes Microsoft.CodeQuality.Analyzers and Microsoft.CodeQuality.CSharp.Analyzers, which is shown as follows:

Moreover, we can also change the rule severity by right-clicking on the rule and selecting the severity, which is shown as follows:

In the preceding picture, rule CA1008 states that Enums should have a value of zero. Let's test this out and see how it works.

Create a simple Enum and specify the values, which are shown as follows:

public enum Status 
{ 
  Create =1, 
  Update =2, 
  Delete =3, 
} 

You will notice as soon as you write this code, it will show the following error and it will provide potential fixes:

Finally, here is the fix we can apply, and the error will disappear:

You can also use one of the popular Visual Studio extensions known as Roslynator, which can be downloaded from the following link. It contains more than 190 analyzers and refactorings for C# based projects: https://marketplace.visualstudio.com/items?itemName=josefpihrt.Roslynator.

Live Static Code analysis is a great feature that helps developers to write quality code that conforms to the best guidelines and practices.

 

Summary


In this chapter, we learned about the .NET Core Framework and some new improvements that are introduced with .NET Core 2.0. We also looked into the new features of C# 7 and how we can write cleaner code and simplify syntactic expressions. Finally, we covered the topic of writing quality code and how we can leverage with the Code analysis feature provided in Visual Studio 2017 to add analyzers into our project which serve our needs. The next chapter will be an in-depth chapter about .NET Core that will cover topics around .NET Core internals and performance improvements.

 

About the Author

  • Ovais Mehboob Ahmed Khan

    Ovais Mehboob Ahmed Khan is a seasoned programmer and solution architect with more than 15 years of software development experience. He has worked in different organizations across Pakistan, the USA, and the Middle East. Currently, he is working with Microsoft as a Premier Field Engineer and based in Dubai. He specializes mainly in Application development, Cloud technologies and DevOps. He is a prolific writer and published numerous technical articles on different websites, such as MSDN, TechNet, DZone, and also an author of three other books published by Packt: JavaScript for .NET Developers, Enterprise Application Architecture with .NET Core and C# 7.0 and .NET Core 2.0 High Performance.

    Browse publications by this author

Latest Reviews

(3 reviews total)
buon riferimento tecnico. Codice chiaro e funzionante. Testato in VS2019
Trying to stay ahead is always a challenge, Packt Publishing makes it easy.
Simply awesome. Industries best quality content to learn new skills or advance existing skills.

Recommended For You

Book Title
Unlock this full book with a FREE 10-day trial
Start Free Trial