Ein Blog

Posts mit Tag "c-sharp"

TIL es gibt ein IAsyncDisposable, das einfach ein IDisposable ist, dessen Dispose-Methode asynchron ist.

.NET 7 Preview 7 ist da. Interessante Neuerungen:

  • Support für Unix File-Modes
  • Ein Ersatz für DllImport (FFI), der Source Generators verwendet: LibraryImport

Weil ich den für .NET 6 auch verlinkt habe: Performance Improvements in .NET 7.

Wie immer beeindruckend.

C# 11 und .NET 7 sind da.

C# hat jetzt wirklich schon echt umfangreiches Pattern-Matching. Z. B. bei dieser Variante von AddAll sieht man das ganz gut:

  T AddAll<T>(params T[] elements) where T : IMonoid<T> =>
    elements switch
  {
      [] => T.Zero,
      [var first, ..var rest] => first + AddAll<T>(rest),
  };

Die List-Patterns lassen code auch schon sehr kompakt (aber zumindest für C# sehr ungewohnt) schreiben und funktionieren auch auf Strings und Char-Spans:

void MatchMessage(string message)
{
    var result = message is ['a' or 'A', .. var s, 'a' or 'A']
        ? $"Message {message} matches; inner part is {s}."
        : $"Message {message} doesn't match.";
    Console.WriteLine(result);
}

MatchMessage("aBBA");  // output: Message aBBA matches; inner part is BB.
MatchMessage("apron");  // output: Message apron doesn't match.

void Validate(int[] numbers)
{
    var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid";
    Console.WriteLine(result);
}

Validate(new[] { -1, 0, 1 });  // output: not valid
Validate(new[] { -1, 0, 0, 1 });  // output: valid

Zu .NET 7 hab ich ja schon einiges hier, vieles davon ist im Ankündigungspost auch noch mal drin.

Preview-Features von C# 12. Die haben echt eine Geschwindigkeit drauf. C# 11 ist gefühlt erst seit 2 Tagen draußen.

TIL: Das scoped-Keyword.

Es ist ja gerade die Build-Konferenz von MS. In der Sessionliste habe ich eine Session gefunden, die ich vor 10 Jahren niemals in einer MS-Konferenz in 10 Jahren erwartet hätte:

What’s New with WinForms in .NET 9?

Wer sich die Stunde sparen will, hier ein paar Highlights:

  • Winforms bekommt Dark-Mode-Support
  • Graphics-Klasse kann jetzt abgerundete Rechtecke zeichnen
  • MVVM für WinForms und generell mehr Data-Binding-Support, Command-Bindings
  • …und natürlich - I kid you not - KI-Integration für diverse Controls. MakeIntelligent-Property auf einem Date-Input und der Textbox. Funktioniert über semantic-kernel, also auch über irgendwelche OpenAI-LLMs. harold.jpg

.NET 10 ist in der ersten preview erschienen. Changelogs:

MS hat in .NET 5 schon deutliche Performancegewinne bei RegEx erzielen können.

Das ist in .NET 7 noch mal interessanter geworden.

Erste interessante Sache: Sie haben einen Source-Generator für RegEx gemacht. Damit wird das RegEx-Pattern zur Compile-Time der Anwendung schon kompiliert. Das spart Zeit bei dem initialen Aufruf und bietet ggf. noch Raum für mehr Optimierungen, weil es nicht zwangsweise schnell gehen muss. Dieser Generator ist allerdings Opt-In, weil man das RegEx-Objekt dafür auf eine bestimmte Art anlegen muss.

RegEx-Engines verwenden in der Praxis üblicherweise Backtracking, um nach Matches zu suchen. Ein Mensch der theoretischen Informatik würde jetzt fragen “warum das?”. Der Hintergrund ist, dass RegEx in den meisten Sprachen doch etwas mehr kann, als reguläre Ausdrücke einer regulären Sprache (z. B. Lookback References).

Verwendet man in seinem Pattern solche Konstrukte (Liste davon ist im verlinkten Blogpost) nicht, kann man alternativ eine RegEx-Engine verwenden, die einen DFA bzw. NFA konstruiert. Also das, was man im TI-Unterricht auch so lernt. Der Vorteil davon: Die können in manchen Use-Cases schneller sein. Das sollte man abhängig von seinem Pattern und den Daten machen. Hilfe beim Entscheiden gibt einem der Blogpost. Man sollte jetzt also nicht hingehen und überall Backtracking entfernen. Backtracking wurde schon gut optimiert.

Ein paar weitere Änderungen sind SIMD-Vektorisierung und Support für Span<T>.

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.