Expression Bodied Members in C# 7

The concept of Expression Bodied Members (EBM) was introduced with C# 6 and as it becomes popular, many enhancements were added with C# 7. Within this article I want to give you the full picture of this feature so I explain the C# 6 and C# 7 EBM features.

With C# 6 the following EBM were introduced:

  • Expression bodied Methods
  • Expression bodied Properties

With C# 7 the following EBM were added:

  • Expression bodied Property Getter
  • Expression bodied Property Setter
  • Expression bodied Indexer
  • Expression bodied Operators Overloading
  • Expression bodied Constructor
  • Expression bodied Destructor (Finalizer)

Syntax

Member methods as well as property getters and property setters are sometimes implemented with a single instruction. In such cases the syntax overhead like brackets or getter and setter syntax is larger than the syntax for the real functionality. EBM allow to reduce the syntax overhead and therefore bring back the focus on the real functionality. This will increase the readability of the source code. For EBM a syntax is used which is already known from lambda expression: the “=>” sign. In contrast to lambda expressions you are limited to a single instruction. I think that’s a really good design decision because the EBM syntax only makes sense in such special cases. If your class members like constructor, property getters or methods contain several instructions, the bracket syntax used so far is more suitable. The instruction which belong together will be written into one block and therefore you can easily see that they belong together. But if you have one instruction only there is nothing which must be grouped. So, in this case it makes sense to leave out the block syntax and use a more lightweight style.

Examples

The following paragraphs show examples for each EBM type. As the examples are quite easily and self-explaining you will not find further descriptions or explanations. But at the end of the article you will find a summary and my personally thinking about the EBM feature.

Each example contains the same implementation twice: one time in EBM syntax and one time in standard block syntax. This allows an easy comparison of both implementation styles. But of course, if you want to compile the source code you must comment out one of the two implementations.

Expression bodied Methods

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  int result = myClass.Sum(3, 5);

  Console.WriteLine(result);
}

class MyClass
{
  // C# 6
  public int Sum(int a, int b) => a + b;

  // C# 5
  public int Sum(int a, int b)
  {
    return a + b;
  }
}

Expression bodied Properties

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  Console.WriteLine(myClass.Value);
}

class MyClass
{
  // C# 6
  public int Value => mValue;

  // C# 5
  public int Value
  {
    get { return mValue; }
  }

  private int mValue = 12;
}

Expression bodied Property Getter and Setter

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  myClass.Value = 42;
  Console.WriteLine(myClass.Value);
}

class MyClass
{
  // C# 7
  public int Value
  {
    get => mValue;
    set => mValue = value;
  }

  // C# 6
  public int Value
  {
    get { return mValue; }
    set { mValue = value; }
  }

  private int mValue = 12;
}

Expression bodied Indexer

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  Console.WriteLine(myClass[2]);
}

class MyClass
{
  // C# 7
  public int this[int index] => mValues[index];

  // C# 6
  public int this[int index]
  {
    get { return mValues[index]; }
  }

  private int[] mValues = new int[] { 11, 12, 13, 14 };
}

Expression bodied Operators Overloading

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  myClass.Value = 15;
  myClass++;

  Console.WriteLine(myClass.Value);
}

class MyClass
{
  // C# 7
  public static MyClass operator ++(MyClass myClass) => new MyClass() { Value = myClass.Value + 1 };

  // C# 6
  public static MyClass operator ++(MyClass myClass)
  {
    return new MyClass() { Value = myClass.Value + 1 };
  }

  public int Value { get; set; }
}

Expression bodied Constructor and Destructor (Finalizer)

static void Main(string[] args)
{
  MyClass myClass = new MyClass();
}

class MyClass
{
  // C# 7
  public MyClass() => Init();
  ~MyClass() => CleanUp();

  // C# 6
  public MyClass() { Init(); }
  ~MyClass() { CleanUp(); }

  private void Init() { }
  private void CleanUp() { }
}

Summary and Assessment

As you can see within the examples, the source code will become more readable as unnecessary syntax overhead is removed. From my point of view EBM is a quite nice feature. But of course, you should not overuse it. EBM should only be used if you have use a simple instruction. Furthermore, I don’t like to use EBM in ctor or finalizer in cases where you want to manage a single resource only. This feels a little bit inappropriate and most often you have more than one resource within a class. If you just want to call a single method in ctor or finalizer EBM is still fine.

Disadvantage of EBM

I think there is one minor disadvantage of EBM. The used ‘=>’ sign looks nearly like the ‘=’ sign. If you mix up these two signs you may write source code with another behavior than expected. The following example shows such an issue.

static void Main(string[] args)
{
  MyClass x;

  for (int i = 0; i  new MyLargeClass();
}

class MyLargeClass
{
  // ...
}

Both implementations look nearly the same but have a different behavior. One is an initializer the other one is a getter. So, in one case the value has a getter only and in the other case a getter and setter. Furthermore, one getter will always return the same object instance and the other one will always create a new object instance. Within the shown example this may result in huge performance differences depending on the kind of the returned object. Of course, this is a rare issue and it will not result in runtime errors. So, this theoretical disadvantage should not stop you from using EBM.

Werbung
Dieser Beitrag wurde unter .NET, C# veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit deinem WordPress.com-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s