Ein Blog

Posts mit Tag "dotnet"

File IO improvements in .NET 6.

Also ich weiß ja nicht, was der Fall ist. Entweder war .NET vorher im Vergleich derbe langsam, oder jetzt, wo es open source ist, kommen da viele Wunderkinder aus den Ecken und optimieren an jeder Stelle, was das Zeug hält. Wie auch immer die solche Performanceverbesserungen aus dem Hut zaubern.

Vielleicht sind es aber auch die Low-Level-Features, die C# seit neustem eins nach dem Anderen dazubekommt, was dazu führt, dass man jetzt solche Optimierungen machen kann. War eigentlich kein Fan davon, weil es in Zukunft immer mehr Wege gibt, Dinge zu tun. Aber ich kann schon verstehen, warum man das will, wenn man damit solche Verbesserungen herzaubern kann.

Interessant ist auch die neue “Thread-Safe File IO”:

We recognized the need for thread-safe File IO. To make this possible, stateless and offset-based APIs have been introduced in #53669 which was part of .NET 6 Preview 7:

An einigen Stellen scheinen sie jetzt auch “am Betriebssystem vorbei” zu gehen (siehe Anmerkung über den File-Offset).

Wenn Ihr früher .NET gemacht habt, kennt Ihr vielleicht noch pinvoke.net. Das ist eine Wiki-artige Plattform, auf der im Prinzip Code gesammelt wurde, um mit der Win32-API über P/Invokes (das ist das FFI von .NET) zu arbeiten.

Jedes Programm hatte dann diese P/Invoke-Signaturen zu sich hinkopiert. Es gab magische Konstanten, die von irgendwo herkamen und keinen Namen hatten. Wie das halt so mit altem Code, der durch 3 Generationen weitergereicht wird, so ist.

Vor kurzem bin ich auf dotnet/pinvoke gestoßen. Das ist genau das, nur von Microsoft selbst (+ Community Contributions), als einheitliche Dependency, die über NuGet installierbar ist. Zugegeben NuGet gab’s vor 15 Jahren noch nicht wirklich in der Form. Aber genau sowas hätte MS auch schon damals bereitstellen sollen - das hätte alles einfacher gemacht. So ähnlich wie mit dem WinAPICodePack, welches dann auf einmal von allen MS-Seiten verschwand (vermutlich wegen Metro/UWP?).

Jedenfalls dachte ich gerade: Geil! Damit kann ich endlich in meiner Software die handgeschriebenen P/Invokes ablösen und die fehlenden nach upstream contributen. Weniger Wartung für mich und alle haben was davon und so.

Dann habe ich aber diese Issue gesehen. Vor einiger Zeit habe ich hier auch etwas zu den Source-Generators in C# geschrieben. Diese Source-Generators lösen genau diese Library jetzt ab. Und zwar hat das Win32-Team Metadata-Dateien erstellt, aus denen die P/Invokes on-demand erstellt werden können. Dieser Source-Generator verwendet das. Man muss damit also keine Dependencys mit riesigen Win32-Import-Ansammlungen mitschleppen, sondern generiert sich genau die, die man benötigt.

C# wird ja immer weiterentwickelt. Das geht seit Roslyn so schnell, dass manche Sachen dort vielleicht untergegangen sind. Z. B. hat C# mittlerweile zwei neue Access-Modifiers, die noch “so üblich” sind:

  • protected internal: The type or member can be accessed by any code in the assembly in which it’s declared, or from within a derived class in another assembly.
  • private protected: The type or member can be accessed only within its declaring assembly, by code in the same class or in a type that is derived from that class.

Wiedermal ein schöner API-gotcha, dieses Mal in C#/.NET:

Path.GetTempFileName() gibt den Pfad zu einer einzigartigen Datei zurück. Dabei wird diese Datei auch gleich (ohne Inhalt) angelegt. Sehr praktisch also! Man kann die Datei auch direkt löschen, wenn man weiß, dass man sie nicht mehr braucht.

Brauchst du etwas mehr, als eine einzige Datei? Es gibt praktischerweise auch Path.GetTempPath()!

Moment — diese Funktion gibt keinen eindeutigen Ordnernamen zurück, sondern den Pfad zum Temp-Verzeichnis des Nutzers. Wer gerade seinen Code refactored hat und davon ausging, dass man den Ordner sicher löschen kann, hat also vielleicht Pech. Wenn man darin dann Dateien mit gleichen Namen anliegt, wiegt sich auch in falscher Sicherheit. Nicht schön.

Dies ist ein schönes Beispiel, dass man Seiteneffekte immer deutlich machen soll. Schon bei GetTempFileName hätte man noch irgendwo ein Create in den Namen tun müssen, damit man sieht, dass diese Funktion auch tatsächlich noch etwas anderes macht, als einen String zurückzugeben. Alternativ hätte man auch bei GetTempPath noch einen anderen Namen finden können.

Naming things is hard.

Heute kam eine Folge von DotNetRocks zu 20 Jahren C# mit Anders Hejlsberg.

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.

.NET 8 ist da.

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 9 ist da. Hier sind die Performance-Verbesserungen.

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

.NET 10 bekommt ein neues GC-Feature: DATAS. War eigentlich schon bei .NET 9 da, aber das benutzen kaum welche, weil es nicht LTS ist.