C#9 – What’s new?

22.01.2021

C# 9.0 ist da und ist in der neu veröffentlichten .NET 5 Version verfügbar. Wir haben für euch bereits einen Blick darauf geworfen und die Änderungen unter die Lupe genommen.

Die Init-only-Setter, ab C# 9.0 ist es nun möglich, Objektmember während der Initialisierung einen Wert zuzuweisen – nach diesem Zeitfenster sind sie dann schreibgeschützt.

public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

var person = new Person {FirstName="Andreas", LastName="Nuber"}; //OK
person.LastName = "Sufin"; //Error !!

Das nächste Feature ist das verbesserte Pattern matching. Diese wurden in dem Sinne verbessert, dass keywords wie notand und or verwendet werden können. Diese Verbesserungen können wenn richtig eingesetzt, die Lesbarkeit des Codes erheblich verbessern. Bekannt ist dieses Feature bereits unter anderem in ähnlicher Form aus Python.

int number = 10;
 
if(number is null and not 12){
    return number+1;
}

Des Weiteren ist mit der target-typed new expression die Möglichkeit gegeben, nur das keyword new() zu verwenden, um eine neue Instanz zu initialisieren. Diese kann aber logischerweise nur verwendet werden, wenn bei der Deklaration der Typ der Variable bekannt ist.

List<string> strignList = new();
var stringList2 = new List<string>();
 
Person person1 = new(20, "John");  //Konstruktor Person(int age, string name) 
Person person2 = new(name: "Hans");  // Wenn Optionale Parameter, kann der gewollte expliziet dadurch gesetzt werden
 
List<int> intList = new()
{
     12,
     13
};

Die Top-Level-Statements erleichtern es, allgemeine Anweisungen zu verkürzen. Dadurch erreicht man ein Skript-Look-a-Like à la Python. So kann ein typisches „Hello World“ mal schnell zu einem Ein-Zeiler werden. Wichtig dabei ist, diese Art Von Top-Level-Statement darf nur einmal im C# Projekt vorkommen. Es ersetzt die main() Methode, welche dann nicht mehr zwingend erforderlich ist.

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

Das „Hello World“ als Top-Level-Statement (class und Main Methode werden nicht benötigt):

System.WriteLine("Hello World");
 
// oder zwei Zeilen
 
using System;
Console.WriteLine("Hello World");

Bei den lambda expressions kann nun der staticmodifier genutzt werden. Es entspricht so einer lokalen static-Methode, die ebenso keine nicht-statische Variablen verwenden können. Ebenso kann nun auch der discardParameter verwendet werden, um explizit zu zeigen, dass manche Parameter nicht benötig werden. Hier werden discards genauer betrachtet.

//Lambda mit static-modifier ohne const Objekt
string y = "Hallo";
 
someMethod(static x => x + y); //Error!!

//Lambda mit static-modifier für const Objekt 
const string y = "Hallo";
 
someMethod(static x => x + y); //OK

In C# 9.0 ist es möglich, Attribute bei lokalen Methoden zu setzten. Zum Beispiel kann die nullable Annotation auf lokale Methoden gesetzt werden.

Covariante returntyps sind bereits aus Java bekannt. Hierbei gibt eine überschreibende Methode einen Typ zurück, der von der überschriebenen Basisklasse abgeleitet wurde. Dadurch kann die Methode einen typspezifischen Rückgabewert zurück liefern.

Performance

Auch wurden in C#9 weitere Performance Verbesserungen umgesetzt, welche eine bessere Laufleistung erzielen lassen.

Native sized integers haben, wie der Name schon suggeriert, eine native Größe, abhängig des Systems. Dieser neue Datentype wird durch nint oder nuint repräsentiert.  Der Typ ist auf 32-Bit-System 32 Bits groß. Analog beträgt er auf 64-Bit-Systemen 64 Bit. Achtung: nint lässt sich nicht mit int vergleichen! Das Ergebnis hier wäre falsch.

Das localsinitFlag ist ein Standardverhalten von C# seit Version 1.0. Dabei werden alle lokalen Variablen mit 0 (oder null) initialisiert. Dies kann in manchen Szenarien Leistungseinbußen hervorrufen. Mit dem SkipLocalsInitAttribute kann jetzt bei classstruct, interface und module dieser Vorgang übersprungen werden.

Record types sind in C# 9.0 ebenfalls neu eingeführt worden. Hiermit lassen sich immutable Klassen abbilden. Das keyword verleiht einer Klasse ein „value-like behavior“. In dieser Hinsicht sind records näher an structs, allerdings handelt es sich hier Referenztypen.

public record Person {
 
   public string Voraname;
   public string Nachname;
 
}

Person person = new();
person.Vorname = "Daniel" //Error!!
 


public record Auto {
   public string Marke { get; init; }
   public int Baujahr { get; init; }
}

Auto auto = new(){ Marke = "Tesla", Baujahr = 2017}; //OK

 

Mit dem ModuleInitializer Attribute können nun bestimmte Methoden als Initialisierung dienen, indem einfach über die gewollte Methode das Attribute gesetzt wird. Folgende Bedinungen müssen dafür erfüllt sein:

Die Methode:

  • muss statisch sein
  • muss parameterlos sein
  • muss void sein
  • darf keine generische Methode sein
  • darf in keiner generischen Klasse sein
  • muss public oder intern sein
namespace CSharp9
{
     class Programm
     {
          public static string test;
 
          public static void Main(string[] args)
          {
              Console.WriteLine(test); // Ausgabe: Hello World
          }
 
          [ModuleInitializer]
          public static void Init()
          {
                test = "Hello World!";
          }
     }
}

Tl;dr: Eine sehr gute Übersicht über die neuen Features von C#9 liefert Christian Nagel hier.


Co-Autor: Daniel Sufin

 

Quellen: 
Zurück zur Übersicht

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*Pflichtfelder

*