Sunday, June 15, 2014

Visual Studio 14 with C# 6.0 released

Microsoft has made Visual Studio 14 available to download as Community Technology Preview. It ships with a new compiler for C# and VB written in the languages themselves with the open code available on CodePlex.
Here are my first impressions on new language constructs in C# 6.0 and Visual Studio 14 enhanced editor features.

C# 6.0 language features

Primary constructor

Is defined along with class definition:
  class C(Action subscriber)
  {
    public event Action SomethingHappened = subscriber;
  }
is equivalent to:

  class C
  {
    public C(Action subscriber)
    {
      SomethingHappened = subscriber;
    }
    public event Action SomethingHappened;
  }

What's interesting if I changed the operator from = to += in the event examples above, then the first example (with primary constructor) will not compile. I have no idea why this is disallowed.

Properties with initializers

This is a really great feature useful to have initial value set to an automatic property without having to create backing field.

  class X
  {
    public int P1 { get; set; } = 23;
    private int _p2;
    public int P2
    {
      get { return _p2; }
      set { _p2 = value; }
    } = 24;

    public void Dump()
    {
      WriteLine(P1);          //Shows 23
      WriteLine(P2);         //Shows 0
    }
  }

Interestingly, as shown above you can assign initial value even to a property with accessors implemented but there's no way you could use that value. I find this weird and a bit inconsistent with events. Because you can initialize event (which I understand as a kind of property) with an initial value, you can't do that when the event has accessors defined:

  event Action E = Console.WriteLine; //OK

  event Action E
  { add { } remove { } }
   = Console.WriteLine; //doesn't compile

Declaration expression

Although minor this is the feature I like the most, it makes the parsing and getting from dictionary code much shorter.

  var dict = new Dictionary<string, string>()
  {
    { "Key1", "Value1" }
  };

  if(dict.TryGetValue("Key1", out var value))
  {
    WriteLine(value);
  }

Static imports

Allow to apply using directive to static classes thus use methods and fields from these classes without providing class name.

  using System.Linq.Enumerable;
  using System.Math;

  var numbers = new List<int>() { 1, 2, 3, 4, 5, 6 };
  var result = Round(Average(numbers)) * PI;

  //instead of

  var res = Math.Round(numbers.Average()) * Math.PI;

I imagine static imports can be useful in unit tests to create more readable assertions. I wonder also why these kinds of import is limited to static classes only forbidding static methods from non static classes and structs.

Null-propagation operator

For many this is the most awaited feature.

  string someString = null;
  var result = someString?.Substring(0, 1); //No null reference exception, result set to null

The operator simplifies checking against null and I like the idea of it. But I hope I will not have to use it often since aggressive checking for null everywhere makes the code ugly. I am passionate about ideas like boundaries for null and null object pattern.

There are also some enhancements to exception handling like conditional catch block execution and awaitable calls in catch block.

Visual Studio 14 editor features

Renaming (Ctrl + R + R)

It's really fast and nimble. It works lot faster than ReSharper renaming I think. It could, however, be more sophisticated with renaming of related identifiers e.g. update object names when renaming classes or update backing field when renaming property.

Quick fixes (Ctrl + .) and Refactorings (Alt + .)

They show a preview on a popup.
I love the support you get from quick fixes when you type the code. But for me the preview functionality wouldn't be very useful. I know how the code is going to be changed at the moment I see the light bulb suggestion.

Unlike quick fixes there are no visible suggestions for refactorings and this is a bit uncomfortable. For example in the code below you have to mark the hello + "World" code fragment and then press Alt + . to force IDE to show you the refactoring option. There's no way to show them until the fragment is precisely selected.



Extract methods (Ctrl + R + M)

This is very cool and does not show this annoying popup like Resharper shows.

Other options

Other features include reorder parameters Ctrl + R + O and remove parameters Ctrl + R + V which basically open the same dialog to manage parameters. I would prefer this as a single functionality called Edit parameters and assign it single shortcut.

What's a bit worrying is the delay in code analysis. When you, for instance, change something in the code that makes it uncompilable you have to wait a short but noticeable amount of time for the problematic code fragment to became underlined. Resharper analysis is more immediate I think.

Cannot extract interface (Ctrl + R + I) when there are no public methods in type - if would be nice if it asked to change some to public.

Unfortunately what Visual Studio offers in terms of refactorings is a small subset of what for example Resharper does. But I know that this is a matter of taste. I would be very happy if Visual Studio offered some more fixes and refactorings built in (like go to implementation - on interface method, introduce and initialize field from constructor, add parameter to methods), which I hope would be faster than the ones from external plugins.

Summary


On the whole I like the new features introduced. There aren't very big but I know the most significant effort was spend on the new compiler. The team encourages to submit any problems or suggestions on the Roslyn page on Codeplex. I was very excited to use it and see how new features work and I also submitted a few bugs to the compiler and IDE.

1 comment: