Feb 27, 2015

C#6, sugar

Here I will cover some of the new features of C# 6, which is not released yet, but the features set seems to be stable enough. I’m interested in all the ways I could write code more effective – less typing, more power. Ok, I could generate the code with Resharper or whatsoever, but why even bother? Lets get rid of the code that does not provide value.
All those features does not require new CLR, they are just syntactic sugar (by the way, the whole C# is just a syntactic sugar for IL), so I decided to take a look what they compile to.
I used Jon Skeet’s post as a reference.
Read-only properties initialization
At the first glance they should compile into field initialization – and they are. There are two options, init property in place or in constructor:

public class AutoProps
{
    public string InitInPlace { get; } = "HasThisVal";
    public string InitInCtor { get; }
    public AutoProps()
    {
        InitInCtor = "from ctor";
    }
}

The major difference there is that init in place looks like field initialization, which does not allow you to use instance members) and behaves that way too. Well, I asked dotPeek to tell me what does he think about that, and here is how the code looks like after decompilation:
public class AutoProps
{
  [CompilerGenerated]
  [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  private readonly string \u003CInitInPlace\u003Ek__BackingField;
  [CompilerGenerated]
  [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  private readonly string \u003CInitInCtor\u003Ek__BackingField;

  public string InitInPlace
  {
    get
    {
      return this.\u003CInitInPlace\u003Ek__BackingField;
    }
  }

  public string InitInCtor
  {
    get
    {
      return this.\u003CInitInCtor\u003Ek__BackingField;
    }
  }

  public AutoProps()
  {
    this.\u003CInitInPlace\u003Ek__BackingField = "HasThisVal";
    base.\u002Ector();
    this.\u003CInitInCtor\u003Ek__BackingField = "from ctor";
  }
}

And, they both are actually initialized in constructor, the difference is only in the order.
Automatically-implemented properties initialization
The same as in place initialization for read-only properties.
Expression-bodied members
That is a shorthand for read-only properties, operators and methods – which consist from a single statement. That’s basically is shorter way to write method body – and there is no surprises in compilation results.
nameof
Finally, no need to maintain string literals while logging, throwing e.t.c. Compiles into string literal (concatenating with surrounding strings if necessary).
Dictionaries initialization
The new dictionaries initialization syntax does not look very different:
public Dictionary<string, int> CreateDictionaryOldWay()
{
    return new Dictionary<string, int>() {
        {"a", 1},
        {"b", 2},
        {"b", 4},
        {"c", 3}
    };
}
public Dictionary<string, int> CreateDictionaryNewWay()
{
    return new Dictionary<string, int>()
    {
        ["a"] = 1,
        ["b"] = 2,
        ["b"] = 4,
        ["c"] = 3
    };
}

The major difference is in the code it compiles to, while the old way initialization compiles to Add method calls -
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add("a", 1);

the new way uses indexers instead -
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary["a"] = 1;
Using for static classes
Now it is possible to reference static classes in using directive – and this will bring fields, methods and properties of that class into scope without necessity of referencing them with class name. Compiles into fully qualified names (local members have higher precedence when resolving the member). You are free to include two classes with same member names in usings, but you will not be able to use those members – compiler would not be able to detect which one you want to use.
String interpolation
That is quite complicated feature, from the point of implementation. Compiles to a string.Format call with a bit of auxilliary code.
From
public string GetSentence(string p1, int p2)
{
    return "here I am \{p1}, \{p2}";
}
to
public string GetSentence(string p1, int p2)
{
  string format = "here I am {0}, {1}";
  object[] objArray = new object[2];
  int index1 = 0;
  string str = p1;
  objArray[index1] = (object) str;
  int index2 = 1;
  // ISSUE: variable of a boxed type
  __Boxed<int> local = (ValueType) p2;
  objArray[index2] = (object) local;
  return string.Format(format, objArray);
}
Null propagation
Simple and effective way to hide null check, however I’m not sure that having a lot of null checks is a good sign.

As the name implies, that is a shortcut for an expression that could result in null value and thus applicable for reference types (nut also supports Nullable struct).

Compiles to a series of null checks, from
class Node
{
    public Node Child { get; set; }
    public int Data { get; }
}
class NullPropagation
{
    public int? GetInfo(Node n)
    {
        return n?.Child?.Data;
    }
}
to
internal class NullPropagation
{
  public int? GetInfo(Node n)
  {
    int? nullable;
    if (n == null)
    {
      nullable = new int?();
    }
    else
    {
      Node child = n.Child;
      nullable = child != null ? new int?(child.Data) : new int?();
    }
    return nullable;
  }
}