C# 7.0

C# 7.0 – what’s new

C# 7.0

C# 7.0 was released a year ago.

C# 7.0 adds a number of new features and brings a focus on data consumption, code simplification and performance.

Here is a summary of the Channel 9 video describing the main features of C# 7.0.

Click on the section headers to jump to that part of the video.

Binary Literals

C# now has syntax to express binary numbers as literals. Similar to the syntax for hexadecimal literals – 0xFFDE you specify a binary number by using the 0b prefix.

Also, digit separators have been added to make literals more readable.

var setBits = 0b10010011; // Binary literal
var readableBits = 0b1001_0011_1110_1011;
// use underscore to separate parts of the literal for readability
var readableHex = 0xACDF_546C_3201;
var readableDec = 12345_67890___98765;
// works with any numeric literal type


Tuples allow you to group a few values together – and return them as well.

All Tuples receives the names Item1, Item2, etc. But, you can name the Tuple elements when you declare it and use those names instead. The Item1, etc. names will still be available.

Tuples are a struct type and are mutable.

var t = Tally(numbers);
WriteLine($"Sum: {t.Item1}, count: {t.Item2}"); // use Item1... to access elements

WriteLine($"Sum: {t.sum}, count: {t.count}"); // or use declared names

(int sum, int count) Tally(params int[] numbers) { ... }

var p = (0, 0); // Tuple literal

var c = (h:0, r:0); // Tuple literal with names

// Tuples assign regardless of names
t = c;

var (sum, count) = t; // deconstruct Tuple

t.sum += 5; t.count++; // Tuples are mutable

Local Functions

Local functions can access members of the scope in which they are declared.

(int sum, int count) Tally(params int[] numbers)
  var rc = (s:0, c:0);
  foreach(var n in numbers)
    Add(n, 1);
  return rc;
  void Add(int s, int c) { rc.s += s; rc.c += c; }

Pattern Matching

Pattern matching is used to test values in various ways.

A constant pattern tests against a constant value – here the constant value null using the is keyword.

if(o is null) return;

The type pattern can be used to test that a value is a particular type. You can also store the result of that expression in a newly declared variable in the same expression

if(!(o is int i)) return;

WriteLine(new string('*', i));

Switch Statements

We can now switch on anything – not just primitives, strings, etc. And patterns can be used in switch statements as well.

switch(shape) // Switch on anything
  case Rectangle s when (s.Length == s.Height): // when condition
    WriteLine($"{s.Length} x {s.Height} square");
  case Rectangle r:
    WriteLine($"{r.Length} x {r.Height} rectangle");
  case Circle c: // type pattern declaring variable c
    WriteLine($"Circle with radius {c.Radius}");
  case null: // case with constants as before
    throw new ArgumentNullException(nameof(shape));
    WriteLine("<unknown shape>");

Learn More

More features are discussed in the blog post below. Things like:

  • Inline out variables
  • Ref returns and locals
  • Generalized async types
  • More expression bodied members – constructors, deconstructors, getters, setters
  • Throw expressions


Nice enhancements.



EDIT: I created a project to contain exploratory tests for these and some C# 6 features. I will add to it over time.


Leave a Reply

Your email address will not be published. Required fields are marked *