C# 7.0 – #7. An improved expression body feature

In C# 6.0 a read-only property like this:

public string SomeProperty
{
    get { return "sometext"; }
}

can be rewritten in a more compact way:

public string SomeProperty => "sometext";

This feature is called “expression body”, but it has some limitations, e.g. the property is turned into field, it only works with read-only properties and not with constructors, deconstructor, getter, setter and so on.

C# 7.0 add all these constructs and then expands the usage of this feature.

Here’s an example, which was taken “as is” from the .Net blog without any test in development environment because by the time of the last released build of Visual Studio 2017 (15.0.26020.0) this new feature doesn’t work yet:

class Person
{
    private static ConcurrentDictionary<int, string> names = new ConcurrentDictionary<int, string>();
    private int id = GetId();

    public Person(string name) => names.TryAdd(id, name); // constructors

    ~Person() => names.TryRemove(id, out *);              // destructors
    
    public string Name
    {
        get => names[id];                                 // getters
        set => names[id] = value;                         // setters
    }
}

C# 7.0 – #6. Usage expanded for statement “throw”

Until C# 6.0 the “throw” keyword must be used only as a standalone statement, that is it cannot be part of an expression. C# 7.0 overcomes this limitation, and then allows this keyword to be placed everywhere, e.g. in the middle of a ternary operator:

string  a = null;
try
{
    // this row doesn't compile in C# 6.0 because of throw statement
    a = a !=  null ? a = " some value" : throw new NullReferenceException("a");
}
catch (Exception ex)
{
    a = "some other value";
    Console.WriteLine("New throw feature: " + a);  // prints "some other value"
}

C# 7.0 – #5. reference return function

In addition to function input parameters, which can be passed by value (default) or by reference (with the keyword ref), in C# 7.0 the value return function can also be returned by reference with the same keyword; furthermore it can be stored in a local variable by reference; this local variable stores the memory address of the data and not the value, and then modifiyng this variable means that every variable that points at the same address would be modified too.

Example:

public struct Point
{
   public int X { get; set; }
   public int Y { get; set; }
}

Point[] arr = new[]
{
   new Point {X=12, Y=15 }, new Point {X=56, Y = 754}, 
   new Point {X=65, Y= 39}, new Point {X=21, Y=63}
};

var p = new Point { X = 65, Y = 39 };
ref Point place = ref Find(p, arr);
place.X = 99;
place.Y = 99;    // replaces 3rd Point element in the array
Console.WriteLine("X=" + arr[2].X + " " + "Y=" + arr[2].Y); // prints X=99 Y=99

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

In this example Point is a structure, and then it is a value type.
The variable called “arr” contains an array (a reference type) of this structure.
The Find method simply searches a value in that array, but it returns the reference of the Point structure founded, and not its value. You can notice the “ref” keyword before the return type and the “ref” keyword after the return statement. Then the code stores this reference in a local “ref” variable (called “place”) containing the reference to the Point structure searched (the third element of the array).
After that the values are modified (X=99; Y=99), and the array element is modified too, which proves that the memory address has been used instead of the value.

C# 7.0 – #4. Local functions

In C# 6.0 there is no way to declare a function which is local to another function, that is a function visible only inside the body in which is declared. The best way to accomplish this is to declare a delegate variable of type Func<T1,TResult> (or one of the several overloads available), ad then use anonymous methods or lambda expression to write the code of the function, as shown here.

// c# 6.0
Func<int, int, int> sum = (k, y) => {
      return k + y;
};

int c = sum(a, b);

This is not an optimal way to use local function, because of some limitations.

C# 7.0 comes with a true local function, and overcomes all the previous limitations.

Here is an example:

int DoSum(int a, int b)
{
   return LocalSum(a, b);

   int LocalSum(int x, int y)
   {
      return x + y;
   }
}

This is a more natural way to declare and use a local function.

C# 7.0 – #3. New Tuple value type

First of all, at least for C# 7.0 included in Visual Studio 2017 RC, it needs to download the System.ValueTuple Nuget Package, providing the System.ValueTuple structs, which implement the underlying types for C# 7 tuples.

In C# 6.0 after invoking an appropriate Tuple object constructor, the object magically contains a series of properties named Item1, Item2 and so on, one for each type parameter.
There wasn’t an easy way to rename the property names with most significant one.
The best way to accomplish this is to create a custom class that inherits from System.Tuple and then expose the Items properties with significant names.

C# 7.0 comes with a much better Tuple object. First of all it is a value type, then it performs faster (reference type can still be used).

A Tuple variable, known as Tuple literal, containing multiple values each of which may have its own data type:

var axes = ("Axis X", "Axis Y", "Axis Z");
Console.WriteLine("Axes are: {0}, {1} and {2} ", axes.Item1, axes.Item2, axes.Item3);
Console.WriteLine($"Axes are: {axes.Item1}, {axes.Item2}, {axes.Item3}");

Members type are automatically inferred by the compiler, in the above example are string, string, string. Furthermore, it’s possible to override the default named Tuple public properties ItemX

var points = (x: 100, y: 20, z: 50);
Console.WriteLine("Points are : {0} , {1}, {2} ", points.x, points.y, points.z);

And different data types are also possible:

var customerInfo = ("Joe Doe", 10, false); //(string,int,bool)
Console.WriteLine("Customer information: Name: {0}, Discount: {1}, IsProspect: {2} ", customerInfo.Item1, customerInfo.Item2, customerInfo.Item3);

A Tuple member may be a reference type:

var customerInformation = (customer: new Customer { FirstName = "Foo", LastName = "Bar" }, Id: 1 );
Console.WriteLine("Customer details are - Id: {0}, First Name: {1}, Last Name: {2}", customerInformation.Id, customerInformation.customer.FirstName, customerInformation.customer.LastName);

public class Customer
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
}

A function may return a Tuple literal:

(string description, double x, double y, double z) GetMultipleValues()
{
   return ("Short description", 100D, 120D, 140D);
}

In this case the funcion gets called in this way:

var values = GetMultipleValues();
Console.WriteLine("Values are: string value={0}, first double value={1}, second double value={2}, third double value={3}", values.Item1, values.Item2, values.Item3, values.Item4);

The return statement in the above function may contain the explicit name of each field:

return (description: "Short description", x: 100D, y: 120D, z: 140D);

So in this way the function would get called:

var values = GetMultipleValues();
Console.WriteLine("Values are: string value={0}, first double value={1}, second double value={2}, "third double value={3}", values.description, values.x, values.y, values.z);

C# 7.0 – #2. Numbers code readability

These are some minor but nice improvements regarding numbers code readability:

Now it is possible to write digit separator of number literals:
The digit separator is the “_” character, like in Java language, isn’t it ?

int number = 1_345_782
Console.WriteLine(number); // prints 1345782

This is mostly useful for large numbers.
The separator is ignored by the compiler; it’s just used to improve the numbers readability, and it can be placed anywhere inside the number, but only inside, not at beginning or at the end for instance:

// this not compile
int number = _1_345_782
int number = 1_345_782_

Strange but true, the separator can be multiple, i.e. you can place more than one separator one beside another:

// this is allowed
int strangeNumber = 1_____2______3______4______5;

For decimal number, it cannot be placed right before the separator character:

// this not compile
double numberDouble = 12_.34;

Same for type specifier:

// this not compile
float numbewFloat = 12_f;

Finally it is available the literal for binary constant values (0b):

int binaryNumber = 0b0100_0010;
Console.WriteLine(binaryNumber); // prints 66

C# 7.0 – #1. New out parameter usage

In C# 7.0 using an out variable is simpler than in older version of the language.
In a nutshell an out variable doesn’t need to be declared anymore before its usage, but can be inline declared just before use it, as shown here:


var n = "2";
//pre-declaration for out parameter variable isn't required anymore
//int p;
//inline declaration for out parameter variable.
int.TryParse(n, out int p);
Console.WriteLine(p);

Furthermore, it’s possible to use the var keyword to inline declare the variable, and not the specific type only, as you would do with C# 6.0 with not initialised pre-declared variables.


var n = "2";
int.TryParse(n, out var p2);
Console.WriteLine(p2);

The inline declared out variables are in scope with the code block that contain them, then they can be used after the declaration inside that block.

If you don’t care about some out function parameter you can complitely ignore them by using wildcards (the “_” symbol).


var n = "2";
int.TryParse(n, out int _);