Wednesday, March 28, 2018

C# 7 New Features


C# 7 adds a number of new features and focuses on data consumption, code simplification and performance. The biggest features have already been considered - tuples, local functions, matching with the pattern and throwing expressions. But there are other new opportunities, both large and small. They all combine to make the code more efficient and understandable, so that everyone is happy and productive.

Let's look at the rest of the features of the new version of C #. So! Let's start!

Out

Currently, in C #, using out parameters is not as flexible as we would like. Before calling a method with out parameters, you first need to declare the variables to pass to the method. Because these variables are usually not initialized (since they will be overwritten by the method), you can not use var for their declaration, so you must always specify the full type:

public void PrintCoordinates(Point p)
{
  int x, y; // have to "predeclare"
  p.GetCoordinates(out x, out y);
  WriteLine($"({x}, {y})");
}

Literals Improvements



var d = 123_456;
var x = 0xAB_CD_EF;

You can put this _ symbol anywhere between the numbers the right number of times to improve readability. It does not affect the value. This separator can be used with the types byte, int, long, decimal, float and double.



Ref returns and locals

You can now pass method parameters by reference (with the ref modifier), you can also return them by reference, and also save them by reference in local variables.


public ref int Find(int number, int[] numbers)
{
  for (int i = 0; i < numbers.Length; i++)
  {
    if (numbers[i] == number)
    {
      return ref numbers[i]; // return the storage location, not the value
    }
  }
  throw new IndexOutOfRangeException($"{nameof(number)} not found");
}

int[] array = { 1, 15, -39, 0, 7, 14, -12 };
ref int place = ref Find(7, array); // aliases 7's place in the array
place = 9; // replaces 7 with 9 in the array
WriteLine(array[4]); // prints 9

This is useful for returning specific fields from large data structures. For example, a game can contain its data in a large pre-distributed array of structures (to avoid pauses in garbage collection). Now methods can return a reference directly to such a structure through which the calling method can read and modify it.

There are some security limitations:


  • You can return only those links that are "safe to return": only those that were sent to you, and those that point to fields in objects
  • Local ref variables are initialized in a specific storage location and can not be changed to point to another

Returned generic types in async methods


Until now, async methods in C# have to either return void, Task, or Task <T>. C# 7 allows you to define other types in such a way that they can be returned from the asynchronous method. The return type must still match the asynchronous pattern, which means that the GetAwaiter method must be available. A concrete example: in the .NET Framework, a new ValueTask type is added, allowing you to use this new language feature

Since Task and Task <T> are reference types, allocating memory in performance-affecting segments (especially when allocating memory in limited cycles) can seriously reduce performance. Support for generic return value types allows you to return a small meaningful type instead of a reference type, so you can prevent excessive allocation of memory.


class Program
{
  static Random rnd;

  static void Main()
  {
    Console.WriteLine($"You rolled {GetDiceRoll().Result}");
  }

  private static async ValueTask GetDiceRoll()
  {
    Console.WriteLine("...Shaking the dice...");
    int roll1 = await Roll();
    int roll2 = await Roll();
    return roll1 + roll2;
  }

  private static async ValueTask Roll()
  {
    if (rnd == null)
    rnd = new Random();

    await Task.Delay(500);
    int diceRoll = rnd.Next(1, 7);
    return diceRoll;
  }
}

No comments:

Post a Comment