C#11 – what’s new

09.03.2023

Zusammen mit .NET 7 wurde auch eine neue Version von C# veröffentlicht. Diese Version kann zwar eingeschränkt auf älteren .NET-Versionen verwendet werden, jedoch bietet Microsoft keinen technischen Support. Offiziell wird C# 11 nur in Verbindung mit .NET 7 unterstützt. Welche Features und spannenden Neuerungen dazugekommen sind, haben wir für euch hier zusammengefasst.

Raw Literal Strings

C#11 stellt eine neue Methode zum Anlegen von unformatierten Zeichenfolgenliteralen bereit. Mit drei oder mehr Anführungszeichen, am Anfang und am Ende, ist es möglich Raw Literal Strings zu definieren. Diese können Umbrüche abbilden und unterstützten Interpolation . Damit sind keine Steuerzeichen, wie Escape-Sequenzen (\n etc.),  mehr notwendig. Zudem sind innerhalb der Zeichenketten-Interpolationsausdrücke Zeilenumbrüche und Kommentare erlaubt.

var name = "DoubleSlash";
var website = "https://www.doubleslash.de/";
var webseiteAndName = $$$""" 
{        
            "Company": {
            "Name": "{{name // Name of person
                   }}",
            "Webseite": "{{website // Website in kleinbuchstaben
                         .ToLower()}}"
            }     } 
""";

.NET-Basisdatentypen

Vor C#11 waren nur Standards in der UTF-16 Codierung möglich. Jedoch benötigen Webanwendungen noch oft Zeichenketten im UTF-8 Standard. Mit dem neuen Update ist dieser Standard nun auch vorhanden.  Vorsicht, mit String Interpolation und Standardwerten für Parameter kann der UTF-8 Standard nicht verwendet werden.

ReadOnlySpan<byte> s1 = "Hallo Reader!"u8;
var s2 = "Hallo Reader!"u8;
byte[] s3 = "Hallo Reader!"u8.ToArray();

Lokale Dateitypen

Zu den bisher bekannten Sichtbarkeitstypen wie public, private etc. wurde nun auch file eingeführt. Damit werden Typen nur innerhalb der Datei sichtbar, in der sie deklariert werden. Hierdurch ist es möglich, mehrere kleine Typen in einer Datei zu deklarieren. Ein Anwendungsbeispiel wäre eine Klasse die eine eigene persönliche, nur für die Klasse geltende Datenstruktur, in Form einer anderen Klasse enthält. Eingeführt wurde dieser Scope für die Source Generatoren, die damit Hilfsklassen erzeugen können, ohne in Konflikt mit anderen Generatoren zu geraten.

Required Members

Für Fields und Properties gibt es den Zusatz required. Mit den Required Members kann der Konstruktor zur Initialisierung der Werte gezwungen werden. Required ist in Klassen, Strukturen und Record-Typen erlaubt, jedoch nicht in Schnittstellen. Im folgenden Codeabschnitt wird die Funktionsweise so wie die Probleme von required aufgezeigt.

public class ComputerScientist
 {
    public ComputerScientist() { }
 
    //Nicht alle erforderlichen Mitglieder
    [SetsRequiredMembers]
    public ComputerScientist(int id) =>
        (ID) = (id);
 
    //Alle erforderlichen Mitglieder
    [SetsRequiredMembers]
    public ComputerScientist(int id, string name) =>
        (ID, Name) = (id, name);
 
    public required int ID;                     // Required Field
    public required string Name { get; init; }  // Required Property
}
 
// 1. Aufruf des Konstruktors mit einer der zwei erforderlichen Angaben -> Nicht erlaubt
var p1 = new ComputerScientist(1);
 
// 2. Aufruf des Konstruktors mit allen erforderlichen Angaben
var p2 = new ComputerScientist(2, "Erika Mustermann");

Zu beachten ist, dass der Code warnungslos auch dann kompiliert wird, wenn [SetsRequiredMembers] nicht alle erforderlichen Mitglieder (ersten Beispiel) setzt.  Der Compiler validiert hier nicht, sondern verlässt sich auf die Angaben von [SetsRequiredMembers].

Static abstract

Neu ist auch die Verwendung von static abstract in Schnittstellen.

// Before C# 11:
public class TypeAttribute : Attribute
{
   public TypeAttribute(Type t) => ParamType = t;
 
   public Type ParamType { get; }
}
//Um das Attribut anzuwenden, wird der Operator typeof verwendet
[TypeAttribute(typeof(string))]
public string Method() => default;
 
// C# 11 feature:
public class GenericAttribute<T> : Attribute { }
 
// Typparameter angeben, um das Attribut zu verwenden
[GenericAttribute<string>()]
public string Method() => default;

Folgende Typparameter sind nicht erlaubt: Nullable Reference Types, Tupel in C#-Syntax (ValueTupel<T,T>)ist aber erlaubt!

.NET-Basisdatentypen

Die neue C# Version bietet jetzt .NET-Basisdatentypen für Zahlen an. Hinzu kommt die Fließkommazahl Half mit 2 Bytes, sowie die Ganzzahlen Int128 und UInt128 mit 16 BytesZudem wurden neue Typaliase für bestehende Basisdatentypen erstellt. Nint und nuint-Typen haben jetzt den Alias System.IntPtr bzw System.UIntPtr jeweils mit 4 oder 8 Bytes.

Nameof

Mit dem nameof Operator ist es jetzt möglich, den Namen eines Methodenparameters in einem Attribut für die Methode oder die Parameterdeklaration anzugeben. Nützlich ist dieses Feature, um den Null-Zustand aller Verweistypvariablen zu bestimmten (nullable-Kontext).

Auto-default Structs

Eine weitere Neuerung sind die Auto-default Structs. Diese ermöglichen, von jedem Feld oder jeder Auto-Eigenschaft, die nicht von einem Konstruktor initialisiert wird, eine automatische Initialisierung vom Compiler mit Standardwerten.

 

Eine vollständige Liste von Neuerungen und Änderungen, sowie eine Liste von Breaking Changes findet ihr hier .


Co-Autor: Sarah Marie Raible

Quellen:

https://www.dotnet-doktor.de/DOTNETDOKTOR/Listen/Blog.aspx

https://learn.microsoft.com/de-de/dotnet/csharp/whats-new/csharp-11#utf-8-string-literals

https://www.it-visions.de/glossar/alle/10534/CSharp_110_C_110.aspx

Zurück zur Übersicht

Kommentar verfassen

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

*Pflichtfelder

*