Ein Blog

Wo wir gerade bei .NET 7 waren:

Die neue Preview (Preview 5) hat jetzt Support für “Generic Math”.

Das wird ermöglicht durch:

  • Statische, abstrakte Interface-Member
  • Dadurch Operatorüberladung, die in Interfaces spezifiziert ist

Interfaces konnten bis C# 11 keine statischen Member von einem Typen verlangen. So war es z. B. nicht möglich, zu verlangen, dass eine Klasse den +-Operator implementiert. Auch nicht mit einem Type-Constraint.
Auch das bekannte Muster Parse und TryParse war mehr Konvention als irgendwie erzwingbar, weil beide Methoden statisch sind. Aus dem Grund war eine Lösung, Klassen zu erstellen, von denen es nur eine Instanz gibt. Anders konnte man keinen Type-Constraint erfüllen, der durch Interfaces kam. Darüber habe ich schonmal berichtet.

Jetzt ist das ganze ist jetzt schon deutlich konkreter geworden. Die neuen Interfaces dazu sehen sehr cool aus. Man kann damit jetzt den Großteil der Rechenoperationen abstrahieren.
Den Nutzen kann man gut sehen, weil sie in der LINQ die Min/Max-Funktionen damit ersetzen konnten. Es fällt echt viel doppelter Code weg.
Es liegt jetzt natürlich nah, diese Interfaces auch bei den Vector-Typen aus System.Numerics zu implementieren. Laut den Kommentaren in dem Artikel dazu wird das nicht mehr in .NET 7 passieren.

Auch neu:
.NET hat jetzt eine API, um TARs zu entpacken. Wenn man das mit dem bereits existierenden GZipStream kombiniert, kann man also ganz leicht ohne externe Libraries jetzt eine tar.gz entpacken. Deflate und Brotli gibt es dort übrigens auch.

System.Text.Json kann jetzt anhand von einem Diskriminator-Feld zwischen in verschiedene Basisklassen deserialisieren:

[JsonDerivedType(typeof(Base), typeDiscriminator: "base")]
[JsonDerivedType(typeof(Derived), typeDiscriminator: "derived")]
public class Base
{
    public int X { get; set; }
}

public class Derived : Base
{
    public int Y { get; set; }
}
// ...
Base value = JsonSerializer.Deserialize<Base>(@"{ ""$type"" : ""derived"", ""X"" : 0, ""Y"" : 0 }");
// value is a Derived instance

Was in dem Blogpost nicht steht, aber in der Issue zu der Änderung: Man kann die Property, auf die geschaut wird, wie folgt definieren:

[JsonPolymorphic(CustomTypeDiscriminatorPropertyName = "$case")]

(standardmäßig ist es "$type")

System.IO.Stream hat jetzt ReadExactly und ReadAtLeast.
Das ist cool, weil das normale Read möglicherweise weniger Daten zurückgibt. Dann muss man eigene Logik bauen, um den Rest auch noch zu lesen. Das ist manchmal echt nervig gewesen.
Um das etwas zu entkoppeln, gibt es übrigens noch was anderes: System.IO.Pipelines.

Wenn Ihr eine Library baut, gibt’s noch eine interessante Neuerung:
Das StringSyntaxAttribute. Das kann man an Member und Parameter kleben, um anzugeben, was der entsprechende String so für Daten enthält. So kann man z. B. sagen, dass soein String ein Regex-Pattern oder JSON enthält. Die IDE kann dann entsprechend highlighten und generell ne bessere Editing-Experience geben.

VS gibt’s jetzt auch für ARM64.