Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
C# 7 and .NET Core 2.0 High Performance

You're reading from   C# 7 and .NET Core 2.0 High Performance Build highly performant, multi-threaded, and concurrent applications using C# 7 and .NET Core 2.0

Arrow left icon
Product type Paperback
Published in Apr 2018
Publisher
ISBN-13 9781788470049
Length 300 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Ovais Mehboob Ahmed Khan Ovais Mehboob Ahmed Khan
Author Profile Icon Ovais Mehboob Ahmed Khan
Ovais Mehboob Ahmed Khan
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. What's New in .NET Core 2 and C# 7? FREE CHAPTER 2. Understanding .NET Core Internals and Measuring Performance 3. Multithreading and Asynchronous Programming in .NET Core 4. Data Structures and Writing Optimized Code in C# 5. Designing Guidelines for .NET Core Application Performance 6. Memory Management Techniques in .NET Core 7. Securing and Implementing Resilience in .NET Core Applications 8. Microservices Architecture 9. Monitoring Application Performance Using Tools 10. Other Books You May Enjoy

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)); }
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()}"); 
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:

You have been reading a chapter from
C# 7 and .NET Core 2.0 High Performance
Published in: Apr 2018
Publisher:
ISBN-13: 9781788470049
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime