© DrHitch/Shutterstock.com
Einblicke in C# 6.0

2 Tipps zum Einsatz der neuen Sprachfeatures von C#


Mit C# 6.0 hat Microsoft endlich einmal wieder eine neue Sprachversion vorgestellt, die eine Reihe von neuen Sprachfeatures mitbringt. Strategische Einschränkungen gab es bei der Gestaltung trotzdem noch: Nur solche Features haben es letztlich in diese Version geschafft, die Vereinfachungen bestehender Syntax darstellen, also dem Entwickler das Leben einfacher machen und etwas Tipparbeit ersparen. Man hat sich dagegen entschieden, manche anderen guten Ideen umzusetzen, die „richtiges“ Neuland erschlossen hätten. Dies könnte in zukünftigen Versionen nachgeholt werden, aber dazu gibt es bisher noch keine Versprechungen.

Die Liste aller Neuerungen in C# 6.0 umfasst je nach Interpretation etwa elf Features:

  1. Initializer für Auto Properties
  2. Auto Properties ohne Setter
  3. Funktionen mit Expression Bodies
  4. using static
  5. Der „Null-conditional Operator“
  6. String-Interpolation
  7. nameof
  8. Initializer für Collections mit Indexzugriff
  9. Exception-Filter
  10. Collection-Initializer mit Add-Extension-Methoden
  11. Await in catch- und finally-Blöcken

Auf die ersten sechs Neuheiten in dieser Liste soll im Folgenden eingegangen werden. Alle diese Features bieten praktische Arbeitserleichterung, aber in manchen Fällen gibt es noch einiges mehr zu den Details und Hintergründen sowie potenziellen Einsatzzwecken zu sagen.

Auto Properties

Der erste Punkt ist schnell abgedeckt: Auto Properties können nun direkt mit Werten initialisiert werden:

public int AutoInteger { get; set; } = 42;

Beachten Sie, dass die Syntax am Ende der Zeile ein Semikolon vorsieht, logisch und üblich bei Zuweisungen, aber auch etwas ungewöhnlich im Anschluss an eine Deklaration mit geschwungenen Klammern.

Besonders wichtig wird die Möglichkeit der Initialisierung, wenn das zweite neue Feature zum Einsatz kommt: Auto Properties ohne Getter:

public int AutoReadOnlyInteger { get; } = 42;

Natürlich können die Werte für Auto Properties auch nach wie vor im Konstruktor einer Klasse initialisiert werden. Interessanterweise gilt dies auch, wenn die Property keinen Getter hat:

public class WeekStartDay {
public string Day { get; }

public WeekStartDay() {
Day = "Monday";
}
}

Diese Neuheiten sind nicht revolutionär, vervollständigen aber das Bild bei der Arbeit mit automatischen Properties. Das alte Pattern, in dem eine readonly Property mithilfe eines privaten Setters simuliert wurde, ist somit endlich hinfällig.

Funktionen mit Expression Bodies

Die Idee ist wiederum einfach: Eine einfachere Syntax zur Erstellung von Methoden in Klassen sollte her. Das neue Feature ist eng an Lambda-Ausdrücke angelehnt. Zum Vergleich hier ein Stück Code, mit dem bisher auf Klassenebene ein Lambda-Ausdruck verwendet werden konnte:

public class Logic {
public Func<int, int, int> Add {
get {
return (x, y) => x + y;
}
}
}

Dieser Code verwendete eine Property, um einen Lambda-Ausdruck zurückzugeben. An dieser Stelle soll nicht weiter auf die Gründe für eine solche Entscheidung eingegangen werden, aber mithilfe eines solchen Konstrukts ließe sich dann der Ausdruck etwa so auswerten:

Console.WriteLine(Add(10, 20));

Damit erhielt der Programmierer ein Element in der Klasse, das beim Aufruf aussah wie eine Methode, technisch jedoch keine war. Natürlich bleibt diese Möglichkeit auch in C# 6.0 bestehen, aber nun gibt es außerdem auch folgende Syntax:

public class Logic {
public int Add(int x, int y) => x + y;
}

Es sei ganz deutlich gesagt, dass der Compiler hier eine normale Methode erzeugt. Das Ziel ist es lediglich, dem Programmierer einen kürzeren Ausdruck verfügbar zu machen. Die Implementation der Klasse Logic in diesem Beispiel ist auf IL-Ebene nicht von dieser zu unterscheiden:

public class Logic {
public int Add(int x, int y) {
return x + y;
}
}

Die Bezeichnung des Features „... mit Expression Bodies“ weist auf eine wichtige Einschränkung hin: Es dürfen keine geschwungenen Klammern in dem Ausdruck verwendet werden, um einen Statement Body zu erzeugen. Die Syntax kann somit nur verwendet werden, wenn die fragliche Funktion tatsächlich nichts anderes tut, als einen Rückgabewert zu erzeugen – oder noch nicht einmal das, wie hier:

public void Output(string x) => Console.WriteLine(x);

Die Regeln für die Gültigkeit des Expression Bodys sind dieselben, die schon immer bei Lambda-Ausdrücken in C# angewandt wurden. Es können grundsätzlich alle Arten von Methoden auf diese Art implementiert werden, so wie hier ein Operator:

public static MyType operator +(MyType x, int y) => x.Add(y);

Technisch ist es ein wenig bedauerlich, dass die Implementation in genau dieser Form gewählt wurde. Die Syntax erinnert auf den ersten Blick an die kurze und bündige Form von Funktionsdeklarationen in funktionalen Sprachen, aber leider fehlt ein wichtiges Detail, um diesen Ansatz nun auch in C# umsetzen zu können. Dieses Detail ist sozusagen der Kontext der Funktion. Natürlich hat die hier erzeugte Methode einen Kontext in dem Sinne, dass sie ihre eigenen lokalen Variablen hat. Aber in funktionalen Sprachen ist es auch möglich, Funktionen innerhalb anderer zu erzeugen und somit zu kapseln, wodurch wesentlich komplexere Zusammenhänge in ähnlich prägnanter Schreibweise abgebildet werden können. Zur Illustration hier ein kurzes Beispiel in Haskell:

force xs = go xs 'pseq' ()
where
go (_:xs) = go xs
go [] = 1

O...

Neugierig geworden?

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang