Was ist neu in C# 10:Übersicht

Was ist neu in C# 10:Übersicht

Dieser Artikel behandelt die neue Version der C#-Sprache – C# 10. Im Vergleich zu C# 9 enthält C# 10 eine kurze Liste von Verbesserungen. Im Folgenden haben wir die Verbesserungen beschrieben und erklärende Codefragmente hinzugefügt. Schauen wir sie uns an.

Verbesserungen von Strukturtypen

Initialisierung der Feldstruktur

Jetzt können Sie die Initialisierung von Feldern und Eigenschaften in Strukturen festlegen:

public struct User
{
    public User(string name, int age)
    {
        Name = name;
        Age = age;
    }
    string Name { get; set; } = string.Empty;
    int Age { get; set; } = 18;
}

Parameterlose Konstruktordeklaration in einem Strukturtyp

Ab C# 10 können Sie einen parameterlosen Konstruktor in Strukturen deklarieren:

public struct User
{
    public User()
    {

    }

    public User(string name, int age)
    {
        Name = name;
        Age = age;
    }

    string Name { get; set; } = string.Empty;
    int Age { get; set; } = 18;
}

Wichtig. Sie können parameterlose Konstruktoren nur verwenden, wenn alle Felder und/oder Eigenschaften Initialisierer haben. Zum Beispiel, wenn Sie das Alter nicht festlegen initializer, gibt ein Compiler einen Fehler aus:

Fehler CS0843:Die automatisch implementierte Eigenschaft „User.Age“ muss vollständig zugewiesen werden, bevor die Kontrolle an den Aufrufer zurückgegeben wird.

Anwenden des with-Ausdrucks auf eine Struktur

Früher konnten Sie das with verwenden Ausdruck mit Aufzeichnungen. Mit C#10 können Sie diesen Ausdruck mit Strukturen verwenden. Beispiel:

public struct User
{
    public User()
    {

    }

    public User(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public string Name { get; set; } = string.Empty;
    public int Age { get; set; } = 18;
}

User myUser = new("Chris", 21);
User otherUser = myUser with { Name = "David" };

Es ist klar, dass die Eigenschaft, die wir ändern (in diesem Fall der Name -Feld) muss einen öffentlichen Zugriffsmodifikator haben.

Globale Verwendung

Ab C# 10 können Sie das using verwenden Richtlinie über ein gesamtes Projekt. Fügen Sie die globale hinzu Keyword vor dem using Ausdruck:

global using "Library name"

Also die Verwendung Direktive erlaubt Ihnen, dieselben Namespaces nicht in verschiedenen Dateien zu duplizieren.

Wichtig. Verwenden Sie globale Verwendung Konstruktion VOR Codezeilen, die using enthalten ohne global Stichwort. Beispiel:

global using System.Text;
using System;
using System.Linq;
using System.Threading.Tasks;
// Correct code fragment

Ansonsten:

using System;
using System.Linq;
using System.Threading.Tasks;
global using System.Text;
// Error CS8915
// A global using directive must precede
// all non-global using directives.

Wenn Sie den Namensraum geschrieben haben, der zuvor mit dem global geschrieben wurde Schlüsselwort, die IDE warnt Sie (IDE:0005:Using Direktive ist unnötig ).

Dateibezogener Namespace

Manchmal müssen Sie den Namespace innerhalb der gesamten Datei verwenden. Diese Aktion kann die Registerkarten nach rechts verschieben. Um dieses Problem zu vermeiden, können Sie jetzt den Namespace verwenden Stichwort. Schreiben Sie den Namespace Schlüsselwort ohne geschweiften Klammern:

using System;
using System.Linq;
using System.Threading.Tasks;

namespace TestC10;

public class TestClass
{
    ....
}

Vor C# 10 war es notwendig, Namespace beizubehalten Klammern öffnen sich auf die gesamte Datei:

using System;
using System.Linq;
using System.Threading.Tasks;

namespace TestC10
{
    public class TestClass
    {
        ....
    }
}

Natürlich können Sie nur einen Namespace deklarieren in der Datei. Dementsprechend ist das folgende Codefragment falsch:

namespace TestC10;
namespace MyDir;
// Error CS8954
// Source file can only contain
// one file-scoped namespace declaration

sowie das folgende Stück Code:

namespace TestC10;
namespace MyDir
{
    ....
}
// Error CS8955
// Source file can not contain both
// file-scoped and normal namespace declarations.

Aufzeichnungsverbesserungen

Das Klassenschlüsselwort

C# 10.0 führt das optionale Schlüsselwort ein – class . Das Schlüsselwort class hilft zu verstehen, ob ein Datensatz von einem Referenztyp ist.

Daher sind die beiden folgenden Datensätze identisch:

public record class Test(string Name, string Surname);
public record Test(string Name, string Surname);

Strukturen aufzeichnen

Jetzt ist es möglich, Datensatzstrukturen zu erstellen:

record struct Test(string Name, string Surname)

Standardmäßig die Eigenschaften der Datensatzstruktur sind im Gegensatz zum standardmäßigen Datensatz änderbar die über init verfügen Modifikator.

string Name { get; set; }
string Surname { get; set; }

Wir können die schreibgeschützt festlegen Eigenschaft für die Datensatzstruktur. Dann entspricht der Zugriff auf die Felder dem Standarddatensatz:

readonly record struct Test(string Name, string Surname);

wobei die Eigenschaften wie folgt geschrieben werden:

string Name { get; init; }
string Surname { get; init; }

Die Gleichheit von zwei Datensatzstrukturobjekten ähnelt der Gleichheit von zwei Strukturen. Gleichheit ist wahr, wenn diese beiden Objekte dieselben Werte speichern:

var firstRecord = new Person("Nick", "Smith");
var secondRecord = new Person("Robert", "Smith");
var thirdRecord = new Person("Nick", "Smith");

Console.WriteLine(firstRecord == secondRecord);
// False
Console.WriteLine(firstRecord == thirdRecord);
// True

Beachten Sie, dass der Compiler keinen Kopierkonstruktor für Datensatzstrukturtypen synthetisiert. Wenn wir einen Kopierkonstruktor erstellen und die with Schlüsselwort beim Initialisieren eines neuen Objekts, dann wird anstelle des Kopierkonstruktors der Zuweisungsoperator aufgerufen (wie es beim Arbeiten mit der Datensatzklasse der Fall ist ).

Versiegeln Sie die ToString()-Methode für Datensätze

Wie mein Kollege im Artikel zu den Verbesserungen für C# 9 schrieb, haben Datensätze das überschriebene toString Methode. Es gibt einen interessanten Punkt zur Vererbung im Zusammenhang mit dieser Methode. Die untergeordneten Objekte können den überschriebenen toString nicht erben Methode aus dem übergeordneten Datensatz. C# 10 führt das Sealed ein Schlüsselwort, damit die untergeordneten Objekte den ToString erben können Methode. Dieses Schlüsselwort verhindert, dass der Compiler den ToString synthetisiert Implementierung für alle abgeleiteten Datensätze. Verwenden Sie das folgende Schlüsselwort, um den ToString zu überschreiben Methode:

public sealed override string ToString()
{
    ....
}

Lassen Sie uns einen Datensatz erstellen, der versucht, den toString zu überschreiben Methode:

public record TestRec(string name, string surname)
{
    public override string ToString()
    {
        return $"{name} {surname}";
    }
}

Lassen Sie uns nun den zweiten Datensatz erben:

public record InheritedRecord : TestRec
{
    public InheritedRecord(string name, string surname)
    :base(name, surname)
    {

    }
}

Lassen Sie uns nun eine Instanz jedes Datensatzes erstellen und das Ergebnis in die Konsole eingeben:

TestRec myObj = new("Alex", "Johnson");
Console.WriteLine(myObj.ToString());
// Alex Johnson

InheritedRecord mySecObj = new("Thomas", "Brown");
Console.WriteLine(mySecObj.ToString());
// inheritedRecord { name = Thomas, surname = Brown}

Wie wir sehen können, ist der InheritedRecord hat toString nicht geerbt Methode.

Lassen Sie uns die TestRec leicht ändern notieren und das versiegelte hinzufügen Schlüsselwort:

public record TestRec(string name, string surname)
{
    public sealed override string ToString()
    {
        return $"{name} {surname}";
    }
}

Lassen Sie uns nun zwei Instanzen der Datensätze neu erstellen und das Ergebnis in die Konsole eingeben:

TestRec myObj = new("Alex", "Johnson");
Console.WriteLine(myObj.ToString());
// Alex Johnson

InheritedRecord mySecObj = new("Thomas", "Brown");
Console.WriteLine(mySecObj.ToString());
// Thomas Brown

Und.. woohoo! Der InheritedRecord hat den toString geerbt Methode aus TestRec .

Einfacherer Zugriff auf verschachtelte Felder und Eigenschaften von Eigenschaftsmustern

C# 8.0 hat das Eigenschaftsmuster eingeführt, mit dem Sie auf einfache Weise Felder und/oder Eigenschaften eines Objekts mit den erforderlichen Ausdrücken abgleichen können.

Wenn Sie zuvor eine verschachtelte Eigenschaft überprüfen mussten, konnte der Code zu umständlich aussehen:

....{property: {subProperty: pattern}}....

Bei C#10 müssen Sie nur die Punkte zwischen den Eigenschaften einfügen:

....{property.subProperty: pattern}....

Sehen wir uns die Änderung am Beispiel der Methode an, bei der die ersten 4 Symbole des Namens verwendet werden.

public record TestRec(string name, string surname);

string TakeFourSymbols(TestRec obj) => obj switch
{
    // old way:
    //TestRec { name: {Length: > 4} } rec => rec.name.Substring(0,4),

    // new way:
    TestRec { name.Length: > 4 } rec => rec.name.Substring(0,4),
    TestRec rec => rec.name,
};

Das obige Beispiel zeigt, dass die neue Art des Eigenschaftszugriffs einfacher und übersichtlicher ist als bisher.

Konstante interpolierte Zeichenfolgen

Vorher wurde diese Funktion nicht unterstützt. C# 10 ermöglicht die Verwendung der Zeichenfolgeninterpolation für konstante Zeichenfolgen:

const string constStrFirst = "FirstStr";
const string summaryConstStr = $"SecondStr {constStrFirst}";

Interessante Tatsache. Diese Änderung betrifft nur die String-Interpolation für konstante Strings, d.h. das Hinzufügen eines konstanten Zeichens ist nicht erlaubt:

const char a = 'a';
const string constStrFirst = "FirstStr";
const string summaryConstStr = $"SecondStr {constStrFirst} {a}";
// Error CS0133
// The expression being assigned to
// 'summaryConstStr' must be constant

Zuweisung und Deklaration in derselben Dekonstruktion

In früheren Versionen von C# konnte eine Dekonstruktion Werte ENTWEDER deklarierten Variablen zuweisen (alle sind deklariert), ODER Variablen, die wir während des Aufrufs initialisieren (alle sind NICHT deklariert):

Car car = new("VAZ 2114", "Blue");

var (model, color) = car;
// Initialization

string model = string.Empty;
string color = string.Empty;
(model, color) = car;
// Assignment

Die neue Version der Sprache ermöglicht die gleichzeitige Verwendung von zuvor deklarierten und nicht deklarierten Variablen bei der Dekonstruktion:

string model = string.Empty;
(model, var color) = car;
// Initialization and assignment

Der folgende Fehler ist in der C#9-Version aufgetreten:

Fehler CS8184:Eine Dekonstruktion kann auf der linken Seite keine Deklarationen und Ausdrücke mischen.

Schlussfolgerung

Wie bereits erwähnt, ist die Liste der Änderungen nicht so umfangreich wie in der C#9-Version. Einige Änderungen vereinfachen die Arbeit, während andere zuvor nicht verfügbare Funktionen bereitstellen. C# befindet sich noch in der Entwicklung. Wir freuen uns auf neue Updates der C#-Sprache.

Sie haben noch nichts über die neuen Funktionen von C# 9 gelesen? Sieh sie dir in unserem separaten Artikel an.

Wenn Sie die Originalquelle sehen möchten, können Sie die Microsoft-Dokumentation lesen.