Exploring Visual Studio "15" Preview and Playing with C# 7

This week at Build 2016, Visual Studio "15" Preview has been released. Visual Studio "15" is not to be confused with Visual Studio 2015. The reason for the naming is that Visual Studio 2015 was version 14, so this new release is version 15.

The Installer

Visual Studio "15" Preview comes with 2 flavors of installers: there is the traditional installer and there is also a preview of a new, experimental installer (which has been designed from the ground up) that supports more configurable, faster installations of Visual Studio.

Because this is an early preview release, the new installer doesn't yet support the full set of Visual Studio features. It does, however, install side-by-side with other Visual Studio instances. So if you want to install all components, you need to install Visual Studio Enterprise "15" Preview instead.

GIF of Visual Studio Installer

New Features in Visual Studio "15"

Here are some highlights of the new features that will be available in Visual Studio 15:

  • C++ Compiler update to enhance support for C++11 and C++14 features, as well as preliminary support for certain features expected to be in the C++17 standard
  • 3 new Style Analyzers for Visual C# and Visual Basic (apart from those already introduced in Visual Studio 2015 Update 2)
  • Some C# 7 Prototypes
  • NuGet 3.4
  • Add Conditions to Exception Settings
  • 30-35% faster first launch of Visual Studio
  • Open Solution from a Folder (no need to chose the .sln file)

For a more detailed list of new features you can visit the official Visual Studio "15" page.

Custom Code Style Enforcement

In Visual Studio "15" Preview, you can play around with the initial prototype for customizable code style enforcement. To see the style options supported today, go to Tools > Options > C# > Code Style.

Custom Code Style Enforcement

You can also add Naming rules, for instance, to require methods to be PascalCase.

Playing with C# 7

While the final feature set for C# 7 is still being determined by the Language Design Committee, you can play with some of the language features today in Visual Studio "15" Preview.

You can follow issue #2136 on the dotnet/roslyn GitHub project to keep updated with the feature list for C# 7.

Enabling C# 7 Prototypes

By default, these new language features are not available when you create new projects with Visual Studio "15".

To access the language prototypes we need to add the __DEMO__ conditional compilation symbol to your project. To do this, you can right click your project, choose properties and go to the build tab.

Conditional Compilation Symbol

Local Functions[1]

This is the ability to declare methods and types in your block scope. Let's see an example:

class Program
{
    static void Main(string[] args)
    {
        void testingLocalFunctions()
        {
            Console.WriteLine("Hello World!");
        }

        testingLocalFunctions();
    }
}

If, when you compile this code, you get the compile time error CS8058: Feature 'local functions' is experimental and unsupported; use '/features:localFunctions' to enable. This is because you did not add the __DEMO__ conditional compilation symbol to your project (check above).

Digit Separators[1:1]

The purpose of this feature is to be able to group digits in large numeric literals. This would have great readability impact and no significant downside. Especially with the introduction of Binary Literals (below), it would increase the likelihood of numeric literals being long, so the two features enhance each other.

Example:

int bin = 0b1001_1010_0001_0100;
int hex = 0x1b_a0_44_fe;
int dec = 33_554_432;
int weird = 100_000;
double real = 1_000.111_1e-1_000;

Binary Literals[1:2]

This feature is pretty self-explanatory.

int nineteen = 0b10011;

Pattern Matching[1:3]

Pattern Matching is still very active in discussions on GitHub and it has quite a complex spec.

With pattern matching, we can now create statements like:

int? age = 5;
if (age is int newVal)
{
    Console.WriteLine($"Your age is {newVal}");
}

Note how we are using the is operator and assigning the value to the newVal variable. Pattern matching goes much more into detail than this example; we have barely scratched the surface here. For more information you should read the Pattern Matching for C# spec on GitHub. In the video, at the bottom of this post, Mads Torgersen demonstrates Pattern Matching in more detail.

Ref Returns and Ref Locals[1:4]

Since the first release of C#, the language has supported passing parameters by reference using the ref keyword. Developers that wanted to pass around structured blocks of memory are often forced to do so with pointers to pinned memory, which is both unsafe and often inefficient. Returning values by reference can improve performance in cases where the alternative is either pinned memory, or copying resources. This features enables developers to continue to use verifiably safe code, while avoiding unnecessary copies.

It may not be a feature you use on a daily basis, but for algorithms that require large amounts of memory for different structures, this feature can have a significant positive impact on the performance of your application.

With ref returns we can now:

public static ref TValue Choose<TValue>(
    Func<bool> condition, ref TValue left, ref TValue right)
{
    return condition() ? ref left : ref right;
}

Tuple Literal Syntax[1:5]

Current Syntax:

public Tuple<int, int> Compute(){}

New Tuple Syntax:

public (int x, int y) Compute(){}
// Call the method
var (x,y) = Compute();

Returning Tuples:

public (int sum, int count) Tally(IEnumerable<int> values)
{
    sum = 0; count = 0;
    foreach (var value in values) { sum += value; count++; }
    return (sum,count);
}

Records (or Record Types)[1:6]

This feature is not available in this version of Visual Studio "15"
Records are just types with only properties. It's not the first time that you have classes or structs in your solutions that are just a collection of properties. For example:

public class Cube
{
    public int width;
    public int height;
    public int depth;

    public int Width
    {
        get { return width; }
    }

    public int Height
    {
        get { return height; }
    }

    public int Depth
    {
        get { return depth; }
    }

    public Cube(int width, int height, int depth)
    {
        this.width = width;
        this.height = height;
        this.depth = depth;
    }
}

This is very verbose. With Records, you could write the above in just a line:

public class Cube(int Width, int Height, int Depth)

This statement will generate:

  • The Constructor
  • Read-only properties (so immutable type)
  • Equality Implementations (GetHashCode, Equals, operator ==, operator !=, IEquatable<Cube>, etc...)
  • Default ToString() implementation
  • Pattern Matching support of the is operator

Non-Nullable Reference Types[1:7]

This feature isn't yet available in Visual Studio "15" because it's still under discussion; nevertheless it's still worth a mention because most probably it will make the final version of C# 7. /u/DoctorProfessorson commented on the reddit thread that this feature has indeed been taken out of the C# 7 feature worklist. You can still find the discussion on GitHub Issue #227 and the following is a summary of what had been proposed.

In C# 2.0, the design team introduced Nullable Value Types which are essentially just syntactic sugar around the Nullable<T> class.

Non-nullable reference types are the reverse of that feature. It let’s you declare a reference type that is guaranteed not to be null. On occasions, null isn’t desirable on a reference type. The idea of this feature is to declare the intent that a reference type would allow nulls (string?) or avoid null (string!).

The Future of C#

For those interested in a demo of these features have a look at the following 1 hour video on Channel 9 from day 2 of Build 2016 by Dustin Campbell and Mads Torgersen.


  1. Issue #227 ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎