(Bild: Pincasso/Shutterstock.com)
Eine neue Methode erlaubt die Multiplikation großer Zahlen.
Die Klassen für Ganzzahltypen Int32, UInt32, Int64 und UInt64 bieten jeweils eine neue Methode BigMul() für die Multiplikation, die die Ergebnisse als Int64 und UInt64 bzw. Int128 und UInt128 zurückliefert (ohne Überlauf).
public void BigMul()
{
CUI.Demo();
long Value1 = long.MaxValue;
ulong Value2 = ulong.MaxValue;
Console.WriteLine("Value1: " + Value1.ToString("#,0"));
Console.WriteLine("Value2: " + Value2.ToString("#,0"));
CUI.H1("Normale Multiplikation");
Int128 e1 = Value1 * 2; // Überlauf! -2
UInt128 e2 = Value2 * 2; // Überlauf! 18446744073709551614
Console.WriteLine(e1.ToString("#,0")); // Überlauf! -2
Console.WriteLine(e2.ToString("#,0")); // Überlauf! 18446744073709551614
CUI.H1("Multiplikation mit BigMul()");
Int128 e3 = Int64.BigMul(Value1, 2); // 18.446.744.073.709.551.614
UInt128 e4 = UInt64.BigMul(Value2, 2); // 36.893.488.147.419.103.230
Console.WriteLine(e3.ToString("#,0")); // 18.446.744.073.709.551.614
Console.WriteLine(e4.ToString("#,0")); // 36.893.488.147.419.103.230
}
URL dieses Artikels:
https://www.heise.de/-10331981
Links in diesem Artikel:
[1] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock.com)
In .NET 9.0 kann man neuerdings einen Globally Unique Identifier in der Version 7 mit Zeitstempel erzeugen.
Die .NET-Klasse System.Guid bietet seit .NET 9.0 neben der statischen Methode NewGuid(), die einen Globally Unique Identifier (GUID), alias UUID (Universally Unique Identifier), gemäß RFC 9562 [1] mit reinen Zufallszahlen (Version 4) erzeugt, nun auch eine weitere statische Methode CreateVersion7() mit einem Timestamp und einer Zufallszahl.
Folgender Code zeigt sowohl den Einsatz von NewGuid() als auch den von CreateVersion7():
public void Run()
{
CUI.Demo(nameof(FCL9_Guid));
for (int i = 0; i < 10; i++)
{
Guid guid = Guid.NewGuid();
Console.WriteLine($"Guid v4:\t{guid}");
}
for (int i = 0; i < 10; i++)
{
Guid guid7 = Guid.CreateVersion7();
Console.WriteLine($"Guid v7:\t{guid7}");
}
CUI.Yellow("Warte 1 Sekunde...");
Thread.Sleep(1000);
for (int i = 0; i < 10; i++)
{
Guid guid7 = Guid.CreateVersion7();
Console.WriteLine($"Guid v7:\t{guid7}");
}
}
(Bild: Screenshot (Holger Schwichtenberg))
Der Timestamp ist in UTC-Zeit in den ersten 64 Bits der GUID enthalten.
Zum Extrahieren des Zeitpunkts gibt es keine eingebaute Methode, man kann ihn aber folgendermaßen extrahieren:
public DateTimeOffset GetDateTimeOffset(Guid guid)
{
byte[] bytes = new byte[8];
guid.ToByteArray(true)[0..6].CopyTo(bytes, 2);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
long ms = BitConverter.ToInt64(bytes);
return DateTimeOffset.FromUnixTimeMilliseconds(ms);
}
URL dieses Artikels:
https://www.heise.de/-10316051
Links in diesem Artikel:
[1] https://www.rfc-editor.org/rfc/rfc9562.html
[2] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock)
In C# 13.0 hat Microsoft den Einsatzbereich von ref struct unter anderem zum Implementieren von Schnittstellen erweitert.
Seit C# 7.2 gibt es Strukturen, die immer auf dem Stack leben und niemals auf den Heap wandern können: ref struct. In C# 13.0 hat Microsoft den Einsatz von ref struct erweitert.
Solche Typen können nun:
where T : allows ref struct verwenden.yield verwendet werden. Allerdings darf die Struktur nicht länger leben als der aktuelle Durchlauf des Iterator.Task oder Task<T> liefern, genutzt werden.Weiterhin gilt aber: Wenn man einen Typ als ref struct deklariert, ist ein Boxing nicht mehr möglich. Der Einsatz von ref struct ist daher begrenzt. So kann man beispielsweise kein Array und keine List<T> daraus erzeugen.
Folgender Code zeigt einen eigenen Typ mit ref struct, der eine Schnittstelle implementiert:
internal interface IPerson
{
int ID { get; set; }
int Name { get; set; }
}
// NEU seit C# 13.0: ref struct kann Schnittstelle implementieren
ref struct Person : IPerson
{
public int ID { get; set; }
public int Name { get; set; }
// ToString()
public override string ToString()
{
return "Person #" + ID + " " + Name;
}
}
}
class Client
{
public void Run()
{
Person p = new Person();
p.ID = 1;
p.Name = 2;
Console.WriteLine(p.ID);
Console.WriteLine(p.Name);
// Das ist alles nicht erlaubt!
// IPerson i = p; // Casting auf Schnittstelle
// List<Person> PersonList = new(); // List<T>
// PersonList[] PersonArray = new Person[10]; // Array
}
}
URL dieses Artikels:
https://www.heise.de/-10307583
Links in diesem Artikel:
[1] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock.com)
Eine neue Methode erlaubt die Multiplikation großer Zahlen.
Die Klassen für Ganzzahltypen Int32, UInt32, Int64 und UInt64 bieten jeweils eine neue Methode BigMul() für die Multiplikation, die die Ergebnisse als Int64 und UInt64 bzw. Int128 und UInt128 zurückliefert (ohne Überlauf).
public void BigMul()
{
CUI.Demo();
long Value1 = long.MaxValue;
ulong Value2 = ulong.MaxValue;
Console.WriteLine("Value1: " + Value1.ToString("#,0"));
Console.WriteLine("Value2: " + Value2.ToString("#,0"));
CUI.H1("Normale Multiplikation");
Int128 e1 = Value1 * 2; // Überlauf! -2
UInt128 e2 = Value2 * 2; // Überlauf! 18446744073709551614
Console.WriteLine(e1.ToString("#,0")); // Überlauf! -2
Console.WriteLine(e2.ToString("#,0")); // Überlauf! 18446744073709551614
CUI.H1("Multiplikation mit BigMul()");
Int128 e3 = Int64.BigMul(Value1, 2); // 18.446.744.073.709.551.614
UInt128 e4 = UInt64.BigMul(Value2, 2); // 36.893.488.147.419.103.230
Console.WriteLine(e3.ToString("#,0")); // 18.446.744.073.709.551.614
Console.WriteLine(e4.ToString("#,0")); // 36.893.488.147.419.103.230
}
URL dieses Artikels:
https://www.heise.de/-10331981
Links in diesem Artikel:
[1] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock.com)
Die Zeitkonvertierungsmethoden haben in .NET 9.0 neue Überladungen für mehr Genauigkeit erhalten.
Die Datenstruktur System.TimeSpan gibt es schon seit der ersten Version des .NET Frameworks aus dem Jahr 2002. In .NET 9.0 adressiert Microsoft jetzt eine kleine Herausforderung, die es in all den Jahren gab: Die Konvertierungsmethoden FromMicroseconds(), FromSeconds(), FromMinutes(), FromHours() und FromDays() erwarten als Parameter einen Double-Wert, der als Fließkommazahl aber ungenau ist.
Microsoft führt daher in .NET 9.0 zusätzlich neue Überladungen dieser Methoden ein, die Ganzzahlen – int beziehungsweise long – als Parameter erwarten:
public static TimeSpan FromDays(int days);public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0);public static TimeSpan FromHours(int hours);public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0);public static TimeSpan FromMinutes(long minutes);public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0);public static TimeSpan FromSeconds(long seconds);public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0);public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0);public static TimeSpan FromMicroseconds(long microseconds);Das folgende Beispiel beweist die größere Genauigkeit der neuen Überladungen am Beispiel FromSeconds():
public class FCL9_TimeSpanFrom
{
public void Run()
{
CUI.Demo(nameof(FCL9_TimeSpanFrom));
// bisher
TimeSpan timeSpan1a = TimeSpan.FromSeconds(value: 123.456);
Console.WriteLine($"TimeSpan +123.456sec alt = {timeSpan1a}");
// 00:02:03.4560000
// bisher
TimeSpan timeSpan2a = TimeSpan.FromSeconds(value: 101.832);
Console.WriteLine($"TimeSpan +101.832sec alt = {timeSpan2a}");
// 00:01:41.8319999
Console.WriteLine();
// neu
TimeSpan timeSpan1n = TimeSpan.FromSeconds(seconds: 123,
milliseconds: 456);
Console.WriteLine($"TimeSpan +123.456sec neu = {timeSpan1n}");
// 00:02:03.4560000
// neu
TimeSpan timeSpan2n = TimeSpan.FromSeconds(seconds: 101,
milliseconds: 832);
Console.WriteLine($"TimeSpan +101.832sec neu = {timeSpan2n}");
// 00:01:41.8320000
}
}
(Bild: Screenshot (Holger Schwichtenberg))
URL dieses Artikels:
https://www.heise.de/-10324526
Links in diesem Artikel:
[1] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock.com)
In .NET 9.0 kann man neuerdings einen Globally Unique Identifier in der Version 7 mit Zeitstempel erzeugen.
Die .NET-Klasse System.Guid bietet seit .NET 9.0 neben der statischen Methode NewGuid(), die einen Globally Unique Identifier (GUID), alias UUID (Universally Unique Identifier), gemäß RFC 9562 [1] mit reinen Zufallszahlen (Version 4) erzeugt, nun auch eine weitere statische Methode CreateVersion7() mit einem Timestamp und einer Zufallszahl.
Folgender Code zeigt sowohl den Einsatz von NewGuid() als auch den von CreateVersion7():
public void Run()
{
CUI.Demo(nameof(FCL9_Guid));
for (int i = 0; i < 10; i++)
{
Guid guid = Guid.NewGuid();
Console.WriteLine($"Guid v4:\t{guid}");
}
for (int i = 0; i < 10; i++)
{
Guid guid7 = Guid.CreateVersion7();
Console.WriteLine($"Guid v7:\t{guid7}");
}
CUI.Yellow("Warte 1 Sekunde...");
Thread.Sleep(1000);
for (int i = 0; i < 10; i++)
{
Guid guid7 = Guid.CreateVersion7();
Console.WriteLine($"Guid v7:\t{guid7}");
}
}
(Bild: Screenshot (Holger Schwichtenberg))
Der Timestamp ist in UTC-Zeit in den ersten 64 Bits der GUID enthalten.
Zum Extrahieren des Zeitpunkts gibt es keine eingebaute Methode, man kann ihn aber folgendermaßen extrahieren:
public DateTimeOffset GetDateTimeOffset(Guid guid)
{
byte[] bytes = new byte[8];
guid.ToByteArray(true)[0..6].CopyTo(bytes, 2);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
long ms = BitConverter.ToInt64(bytes);
return DateTimeOffset.FromUnixTimeMilliseconds(ms);
}
URL dieses Artikels:
https://www.heise.de/-10316051
Links in diesem Artikel:
[1] https://www.rfc-editor.org/rfc/rfc9562.html
[2] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock)
In C# 13.0 hat Microsoft den Einsatzbereich von ref struct unter anderem zum Implementieren von Schnittstellen erweitert.
Seit C# 7.2 gibt es Strukturen, die immer auf dem Stack leben und niemals auf den Heap wandern können: ref struct. In C# 13.0 hat Microsoft den Einsatz von ref struct erweitert.
Solche Typen können nun:
where T : allows ref struct verwenden.yield verwendet werden. Allerdings darf die Struktur nicht länger leben als der aktuelle Durchlauf des Iterator.Task oder Task<T> liefern, genutzt werden.Weiterhin gilt aber: Wenn man einen Typ als ref struct deklariert, ist ein Boxing nicht mehr möglich. Der Einsatz von ref struct ist daher begrenzt. So kann man beispielsweise kein Array und keine List<T> daraus erzeugen.
Folgender Code zeigt einen eigenen Typ mit ref struct, der eine Schnittstelle implementiert:
internal interface IPerson
{
int ID { get; set; }
int Name { get; set; }
}
// NEU seit C# 13.0: ref struct kann Schnittstelle implementieren
ref struct Person : IPerson
{
public int ID { get; set; }
public int Name { get; set; }
// ToString()
public override string ToString()
{
return "Person #" + ID + " " + Name;
}
}
}
class Client
{
public void Run()
{
Person p = new Person();
p.ID = 1;
p.Name = 2;
Console.WriteLine(p.ID);
Console.WriteLine(p.Name);
// Das ist alles nicht erlaubt!
// IPerson i = p; // Casting auf Schnittstelle
// List<Person> PersonList = new(); // List<T>
// PersonList[] PersonArray = new Person[10]; // Array
}
}
URL dieses Artikels:
https://www.heise.de/-10307583
Links in diesem Artikel:
[1] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock)
C# 13.0 führt die neue Klasse Lock ein, um Codeblöcke vor dem Zugriff durch weitere Threads zu sperren.
Ab .NET 9.0/C# 13.0 gibt es für das Sperren von Codeblöcken vor dem Zugriff durch weitere Threads die neue Klasse System.Threading.Lock, die man nun im Standard in Verbindung mit dem lock-Statement in C# verwenden sollte, "for best performance" wie Microsoft in der Dokumentation [1] schreibt.
Folgender Code aus der C#-Dokumentation auf Microsoft Learn [2] zeigt ein Beispiel mit dem Schlüsselwort lock und der Klasse System.Threading.Lock:
using System;
using System.Threading.Tasks;
namespace NET9_Console.CS13;
public class Account
{
// Vor .NET 9.0/C# 13.0 wurde hier System.Object verwendet statt
// System.Threading.Lock
private readonly System.Threading.Lock _balanceLock = new();
private decimal _balance;
public Account(decimal initialBalance) => _balance = initialBalance;
public decimal Debit(decimal amount)
{
if (amount < 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "The debit amount cannot be negative.");
}
decimal appliedAmount = 0;
lock (_balanceLock)
{
if (_balance >= amount)
{
_balance -= amount;
appliedAmount = amount;
}
}
return appliedAmount;
}
public void Credit(decimal amount)
{
if (amount < 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "The credit amount cannot be negative.");
}
lock (_balanceLock)
{
_balance += amount;
}
}
public decimal GetBalance()
{
lock (_balanceLock)
{
return _balance;
}
}
}
class AccountTest
{
static async Task Main()
{
var account = new Account(1000);
var tasks = new Task[100];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = Task.Run(() => Update(account));
}
await Task.WhenAll(tasks);
Console.WriteLine($"Account's balance is {account.GetBalance()}");
// Output:
// Account's balance is 2000
}
static void Update(Account account)
{
decimal[] amounts = [0, 2, -3, 6, -2, -1, 8, -5, 11, -6];
foreach (var amount in amounts)
{
if (amount >= 0)
{
account.Credit(amount);
}
else
{
account.Debit(Math.Abs(amount));
}
}
}
}
Der C#-13.0-Compiler generiert dann aus
lock (_balanceLock)
{
_balance += amount;
}
einen Aufruf der EnterScope()-Methode in der Klasse System.Threading.Lock:
using (balanceLock.EnterScope())
{
_balance += amount;
}
URL dieses Artikels:
https://www.heise.de/-10299439
Links in diesem Artikel:
[1] https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/lock
[2] https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/lock
[3] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock)
Man kann in C# 13.0 neuerdings auch mit dem Index vom Ende ein Array initialisieren.
Bisher schon konnte eine Initialisierung von Mengen wie Arrays mit Indexer × = y erfolgen. In C# 13.0 ist eine Array-Initialisierung auch mit Index vom Ende [^x] = y möglich mit dem Index-Operator ^, den es seit C# 8.0 gibt.
Die neue Syntax ist allerdings nur bei der Erstinitialisierung des Objekts möglich, nicht bei anderen Zuweisungen.
Folgendes Codebeispiel zeigt die Objektmengen-Initialisierung mit Index von vorne × und vom Ende [^x]:
namespace NET9_Console.CS13;
internal class CS13_Indexer
{
class ZahlenGenerator
{
public string[] Ziffern = new string[10];
}
/// <summary>
/// C# 13.0: Objekt-Initialisierung mit Index vom Ende [^x] ("Implicit Indexer Access in Object Initializers")
/// </summary>
public void Run()
{
CUI.Demo(nameof(CS13_Indexer));
CUI.H2("Array-Initialisierung mit Indexer von vorne nach hinten");
var dAlt = new ZahlenGenerator()
{
Ziffern = {
[0] = "null",
[1] = "eins",
[2] = "zwei",
[3] = "drei",
[4] = "vier",
[5] = "fünf",
[6] = "sechs",
[7] = "sieben",
[8] = "acht",
[9] = "neun",
}
};
foreach (var z in dAlt.Ziffern)
{
Console.WriteLine(z);
}
CUI.H2("NEU: Array-Initialisierung mit Indexer von hinten nach vorne");
var dNeu = new ZahlenGenerator()
{
Ziffern = {
[^1] = "neun",
[^2] = "acht",
[^3] = "sieben",
[^4] = "sechs",
[^5] = "fünf",
[^6] = "vier",
[^7] = "drei",
[^8] = "zwei",
[^9] = "eins",
[^10] = "null"
}
};
foreach (var z in dNeu.Ziffern)
{
Console.WriteLine(z);
}
CUI.H2("NEU: Array-Initialisierung mit Indexer in beide Richtungen");
var dNeu2 = new ZahlenGenerator()
{
Ziffern = {
[^1] = "neun",
[^2] = "acht",
[^3] = "sieben",
[^4] = "sechs",
[^5] = "fünf",
[4] = "vier",
[3] = "drei",
[2] = "zwei",
[1] = "eins",
[0] = "null"
}
};
foreach (var z in dNeu2.Ziffern)
{
Console.WriteLine(z);
}
CUI.H2("NEU: Array-Befüllung zu einem späteren Zeitpunkt");
// erstelle ein Array von int mit 10 Elementen
int[] array1 = new int[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// das geht nicht, Syntax nur bei Objektinitialisierung im Rahmen der Instanziierung erlaubt
//array1 = {
// [^1] = 9,
// [^2] = 8,
// [^3] = 7,
// [^4] = 6,
// [^5] = 5,
// [0] = 0,
// [1] = 1,
// [2] = 2,
// [3] = 3,
// [4] = 4
// }
// hier geht nur das:
array1[^1] = 9;
array1[^2] = 8;
array1[^3] = 7;
array1[^4] = 6;
array1[^5] = 5;
array1[0] = 0;
array1[1] = 1;
array1[2] = 2;
array1[3] = 3;
array1[4] = 4;
foreach (var item in array1)
{
CUI.LI(item);
}
}
}
URL dieses Artikels:
https://www.heise.de/-10290670
Links in diesem Artikel:
[1] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock)
In C# 13 dürfen bei den variadischen Parametern generische Mengentypen statt eines Array verwendet werden.
Seit der ersten Version von C# gibt es Parameter-Arrays für sogenannte variadische Parameter (vgl. Wikipedia-Eintrag zu variadischen Funktionen [1]), mit denen eine Methode eine beliebig lange Liste von Parametern eines Typs empfangen kann, wenn dies mit dem Schlüsselwort params eingeleitet wird.
Der folgende Code zeigt die bisherige Variante eines variadischen Parameters mit Arrays:
public void MethodeMitBeliebigVielenParametern_Alt(string text,
params int[] args)
{
CUI.H2(nameof(MethodeMitBeliebigVielenParametern_Alt));
CUI.Print(text + ": " + args.Length);
foreach (var item in args)
{
CUI.LI(item);
}
}
Die Methode kann man beispielsweise folgendermaßen aufrufen:
MethodeMitbeliebigVielenParametern_Alt("Anzahl Zahlen", 1, 2, 3);
MethodeMitbeliebigVielenParametern_Alt("Number of numbers",
1, 2, 3, 4);
Neu in C# 13.0 ist, dass statt eines Arrays bei den variadischen Parametern auch generische Mengentypen verwendet werden dürfen (sogenannte Parameter Collections) wie params Span<T>:
public void MethodeMitBeliebigVielenParametern_Neu(string text,
params Span<int> args)
{
CUI.H2(nameof(MethodeMitBeliebigVielenParametern_Neu));
CUI.Print(text + ": " + args.Length); // statt args.Length
foreach (var item in args)
{
CUI.LI(item);
}
}
Analog ist der Aufruf dann genauso flexibel möglich wie beim Parameter-Array:
MethodeMitBeliebigVielenParametern_Neu("Anzahl Zahlen", 1, 2, 3);
MethodeMitBeliebigVielenParametern_Neu("Number of numbers",
1, 2, 3, 4);
Dann sind diese generischen Mengentypen bei params in C# 13.0 erlaubt:
Collections.Generic.IEnumerable<T>System.Collections.Generic.IReadOnlyCollection<T>Collections.Generic.IReadOnlyList<T>System.Collections.Generic.ICollection<T>Collections.Generic.IList<T> Collections.Generic.IEnumerable<T>implementierenSpan<T>ReadOnlySpan<T>Wenn möglich, sollte man die Parameterliste per Span<T> oder ReadOnlySpan<T> übergeben, damit die Parameterübergabe komplett per Stack erfolgt und keinerlei Speicherallokation auf dem Heap erfolgen muss.
Ebenso wie man bei einem Parameter-Array auch ein fertiges Array übergeben kann, das dann auf die Parameter verteilt wird
MethodeMitBeliebigVielenParametern_Alt(
"Anzahl Zahlen - übergeben als Int-Array",
[1, 2, 3]);
kann man auch einen der obigen neuen Typen übergeben, wenn die Methode eine Parameter Collection erwartet:
MethodeMitBeliebigVielenParametern_Neu(
"Anzahl Zahlen - übergeben als List<int>",
new List<int> { 1, 2, 3 });
oder
MethodeMitBeliebigVielenParametern_Neu(
"Anzahl Zahlen - übergeben als List<int>",
[1, 2, 3]);
Achtung: Die folgende Syntax funktioniert aber nicht:
MethodeMitBeliebigVielenParametern_Neu(
"Anzahl Zahlen - übergeben als List<int>",
new List<int> [1, 2, 3 ]);
Das ist nicht möglich, da new List<int> [1, 2, 3 ] ein dreidimensionales Array von List<int> erzeugt.
URL dieses Artikels:
https://www.heise.de/-10282100
Links in diesem Artikel:
[1] https://de.wikipedia.org/wiki/Variadische_Funktion
[2] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Piyawat Nandeenopparit / Shutterstock.com)
Eine neue Annotation ermöglicht es, über Prioritäten explizit festzulegen, welche Methodenüberladung der Compiler aufrufen soll.
Mit [OverloadResolutionPriority] im Namensraum System.Runtime.CompilerServices können Entwicklerinnen und Entwickler festlegen, dass bestimmte Überladungen bei der Entscheidung, welche Überladung verwendet werden soll, eine höhere Priorität erhalten. Das hilft zum Beispiel, wenn mit [Obsolet] annotierte Überladungen einer Methode existieren, um zur präferierten Implementierung zu lotsen.
Bei der neuen Annotation [OverloadResolutionPriority] gibt man eine Integer-Zahl an:
Das folgende Listing zeigt ein Beispiel: Der Aufruf von Print() mit einer Zeichenkette würde ohne [OverloadResolutionPriority] immer zur Implementierung von Print() mit einem String-Parameter gehen, auch wenn diese Überladung als [Obsolete] gekennzeichnet ist. Durch das Einfügen von [OverloadResolutionPriority] lenkt man den Compiler auf eine andere Implementierung um. Würde man in dem Beispiel sowohl der Implementierung mit Parametertyp object als auch ReadOnlySpan<char> den gleichen Prioritätswert geben, wüsste der Compiler nicht, welche Konvertierung er machen soll und verweigert die Übersetzung:
The call is ambiguous between the following methods or properties: 'CS13_OverloadResolutionPriority.Print(object, ConsoleColor)' and 'CS13_OverloadResolutionPriority.Print(ReadOnlySpan<char>, ConsoleColor)'
Mit einem abweichenden Prioritätswert kann man den Compiler zu der einen oder der anderen Implementierung lenken, hier im Listing mit Wert 10 zu public void Print(ReadOnlySpan<char> text, ConsoleColor color).
Die Implementierung public void Print(object text, ConsoleColor color) kommt aber weiterhin zum Einsatz für alle anderen Datentypen, zum Beispiel Zahlen wie 42, denn diese kann der Compiler nicht automatisch in ReadOnlySpan<char> konvertieren.
Folgender Code zeigt den Einsatz der neuen Annotation [OverloadResolutionPriority]:
using System.Runtime.CompilerServices;
namespace NET9_Console.CS13;
public class CS13_OverloadResolutionPriority
{
public void Run()
{
CUI.Demo(nameof(CS13_OverloadResolutionPriority));
// verwendet Print(ReadOnlySpan<char> text)
ReadOnlySpan<char> span = "www.IT-Visions.de".AsSpan();
Print(span);
// verwendet Print(ReadOnlySpan<char> text) wegen OverloadResolutionPriority(10)
Print("Dr. Holger Schwichtenberg");
// verwendet public void Print(object obj)
Print(42);
}
[Obsolete]
//[OverloadResolutionPriority(10)]
public void Print(string text)
{
// Set the console color
Console.ForegroundColor = ConsoleColor.Red;
// Print the text
Console.WriteLine("string: " + text);
// Reset the console color
Console.ResetColor();
}
[OverloadResolutionPriority(1)]
public void Print(object obj)
{
// Set the console color
Console.ForegroundColor = ConsoleColor.Yellow;
// Print the text
Console.WriteLine("Object: " + obj.ToString());
// Reset the console color
Console.ResetColor();
}
[OverloadResolutionPriority(10)]
public void Print(ReadOnlySpan<char> text)
{
// Set the console color
Console.ForegroundColor = ConsoleColor.Green;
// Print the text
Console.WriteLine("ReadOnlySpan<char>: " + text.ToString());
// Reset the console color
Console.ResetColor();
}
}
(Bild: Screenshot (Holger Schwichtenberg))
Wenn man bei public void Print(string text, ConsoleColor color) auch eine Overload Resolution Priority von mindestens 10 setzt
[Obsolete]
[OverloadResolutionPriority(10)]
public void Print(string text, ConsoleColor color)
{
// Set the console color
Console.ForegroundColor = color;
// Print the text
Console.WriteLine("string: " + text);
// Reset the console color
Console.ResetColor();
}
dann wird bei
Print("Dr. Holger Schwichtenberg", ConsoleColor.Yellow);
die Überladung mit string-Parameter genommen, auch wenn diese mit [Obsolete] markiert ist.
URL dieses Artikels:
https://www.heise.de/-10272355
Links in diesem Artikel:
[1] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock.com)
Der Vortrag in Dortmund behandelt die Neuerungen in der Syntax von C# 13.0, der .NET 9.0-Basisklassenbibliothek sowie den Anwendungsmodellen.
Ich möchte Sie kurz auf meinen nächsten ehrenamtlichen User-Group-Vortrag aufmerksam machen.
Am 5. Februar 2025 von 18 Uhr bis etwa 20:30 Uhr halte ich in Dortmund den Vortrag "Was bringen C# 13.0 und .NET 9.0?"
Die Veranstaltung der .NET User Group Dortmund ist kostenlos. Sie findet bei der Adesso AG am Adessoplatz 1, 44269 Dortmund in der ersten Etage statt.
Der Vortrag hat folgende Inhalte:
Hier geht es zur Anmeldung:
Die Teilnahme ist kostenfrei. Eine Anmeldung ist jedoch zwingend erforderlich [1]. Die Teilnehmeranzahl ist durch die User Group auf 60 Personen begrenzt.
Denjenigen, die nicht persönlich zu dem Termin nach Dortmund kommen können oder mehr wissen wollen als ich an dem einen Abend vermitteln kann, empfehle ich alternativ meine vier Bücher zu .NET 9.0 zu lesen [2].Das geht besonders günstig im E-Book-Abo [3] (ab 99 Euro/Jahr). Hierin sind auch die laufenden Updates aller meiner .NET- und Web-Bücher enthalten.
URL dieses Artikels:
https://www.heise.de/-10261744
Links in diesem Artikel:
[1] https://www.it-visions.de/V11610
[2] https://www.it-visions.de/buecher/verlag.aspx
[3] https://www.it-visions.de/BuchAbo
[4] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Valtenint Agapov / Shutterstock)
C# 13.0 bietet ein neues Escape-Zeichen \e für die Formatierung von ANSI/VT100 Terminal Control Escape Sequences.
Mit den uralten VT100/ANSI-Escape-Codes [1] kann man auch heute noch in Konsolenanwendungen zahlreiche Formatierungen auslösen, darunter 24-Bit-Farben, Fettschrift, Unterstreichen, Durchstreichen und Blinken. Die VT100/ANSI-Codes werden durch das Escape-Zeichen (ASCII-Zeichen 27, hexadezimal: 0x1b) eingeleitet.
Vor C# 13.0 konnte man dieses Escape-ASCII-Zeichen 27 in .NET-Konsolenanwendungen bei Console.WriteLine() nur umständlich ausdrücken über \u001b, \U0000001b oder \x1b, wobei Letzteres nicht empfohlen ist [2]: "Wenn Sie die Escapesequenz \x verwenden, weniger als vier Hexadezimalziffern angeben und es sich bei den Zeichen, die der Escapesequenz unmittelbar folgen, um gültige Hexadezimalziffern handelt (z. B. 0–9, A–F und a–f), werden diese als Teil der Escapesequenz interpretiert. \xA1 erzeugt beispielsweise "¡" (entspricht dem Codepunkt U+00A1). Wenn das nächste Zeichen jedoch "A" oder "a" ist, wird die Escapesequenz stattdessen als \xA1A interpretiert und der Codepunkt "ਚ" erzeugt (entspricht dem Codepunkt U+0A1A). ਚ ist ein Panjabi-Schriftzeichen. Panjabi ist eine in Pakistan und Indien gesprochene Sprache. In solchen Fällen können Fehlinterpretationen vermieden werden, indem Sie alle vier Hexadezimalziffern (z. B. \x00A1) angeben."
Typischerweise sahen Ausgaben mit VT100/ANSI-Escape-Codes vor C# 13.0 folgendermaßen aus:
Console.WriteLine("This is a regular text");
Console.WriteLine("\u001b[1mThis is a bold text\u001b[0m");
Console.WriteLine("\u001b[2mThis is a dimmed text\u001b[0m");
Console.WriteLine("\u001b[3mThis is an italic text\u001b[0m");
Console.WriteLine("\u001b[4mThis is an underlined text\u001b[0m");
Console.WriteLine("\u001b[5mThis is a blinking text\u001b[0m");
Console.WriteLine("\u001b[6mThis is a fast blinking text\u001b[0m");
Console.WriteLine("\u001b[7mThis is an inverted text\u001b[0m");
Console.WriteLine("\u001b[8mThis is a hidden text\u001b[0m");
Console.WriteLine("\u001b[9mThis is a crossed-out text\u001b[0m");
Console.WriteLine("\u001b[21mThis is a double-underlined text\u001b[0m");
Console.WriteLine("\u001b[38;2;255;0;0mThis is a red text\u001b[0m");
Console.WriteLine("\u001b[48;2;255;0;0mThis is a red background\u001b[0m");
Console.WriteLine("\u001b[38;2;0;0;255;48;2;255;255;0mThis is a blue text with a yellow background\u001b[0m");
Seit C# 13.0 gibt es nun \e als Kurzform für das Escape-Zeichen ASCII 27, sodass die Zeichenfolgen deutlich kompakter und übersichtlicher werden:
Console.WriteLine("This is a regular text");
Console.WriteLine("\e[1mThis is a bold text\e[0m");
Console.WriteLine("\e[2mThis is a dimmed text\e[0m");
Console.WriteLine("\e[3mThis is an italic text\e[0m");
Console.WriteLine("\e[4mThis is an underlined text\e[0m");
Console.WriteLine("\e[5mThis is a blinking text\e[0m");
Console.WriteLine("\e[6mThis is a fast blinking text\e[0m");
Console.WriteLine("\e[7mThis is an inverted text\e[0m");
Console.WriteLine("\e[8mThis is a hidden text\e[0m");
Console.WriteLine("\e[9mThis is a crossed-out text\e[0m");
Console.WriteLine("\e[21mThis is a double-underlined text\e[0m");
Console.WriteLine("\e[38;2;255;0;0mThis is a red text\e[0m");
Console.WriteLine("\e[48;2;255;0;0mThis is a red background\e[0m");
Console.WriteLine("\e[38;2;0;0;255;48;2;255;255;0mThis is a blue text with a yellow background\e[0m");
(Bild: Screenshot (Holger Schwichtenberg))
URL dieses Artikels:
https://www.heise.de/-10255344
Links in diesem Artikel:
[1] https://en.wikipedia.org/wiki/ANSI_escape_code
[2] https://learn.microsoft.com/de-de/dotnet/csharp/programming-guide/strings/
[3] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock)
C# 13.0 bietet neben partiellen Klassen und Methoden jetzt auch die lang erwartete Umsetzung für partielle Properties und Indexer.
Eine wichtige Neuerung in C# 13.0 sind partielle Properties und Indexer. Auf dieses Sprachfeature warten viele Entwicklerinnen und Entwickler bereits seit der Einführung der partiellen Methoden in C# 3.0. Das C#-Schlüsselwort partial gibt es sogar bereits seit C# 2.0 für Klassen.
Mit partiellen Klassen kann man den Programmcode einer einzigen Klasse auf mehrere Codedateien aufspalten – ohne dafür Vererbung zu nutzen. Das ist nicht nur sinnvoll für mehr Übersichtlichkeit bei umfangreichen Klassen, sondern wird vor allem verwendet, wenn ein Teil der Klasse automatisch generiert und der andere Teil der Klasse manuell geschrieben wird. Diese Vorgehensweise kommt in .NET zum Beispiel bei GUI-Bibliotheken wie ASP.NET Webforms und Blazor, beim Reverse Engineering von Datenbanken mit Entity Framework und Entity Framework Core sowie bei Source-Generatoren (z.B. für reguläre Ausdrücke und JSON-Serialisierung) zum Einsatz.
In C# 13.0 können Entwicklerinnen und Entwickler auch Property- und Indexer-Definition sowie deren Implementierung mit partial in zwei Dateien trennen. Dabei müssen beide Teile jeweils die gleiche Kombination von Getter und Setter mit den gleichen Sichtbarkeiten sowie dem gleichen Typ realisieren.
Ein konkretes Beispiel: Wenn in einem Teil der Klasse eine Property sowohl einen öffentlichen Getter als auch einen öffentlichen Setter besitzt, müssen diese auch im anderen Teil vorhanden und öffentlich sein. Aber während in einem Teil ein automatisches Property verwendet wird, kann im anderen Teil eine explizite Implementierung vorhanden sei.
Partielle Properties und partielle Indexer können genau wie partielle Klassen und partielle Methoden NICHT aus mehreren Projekten/Assemblies zusammengeführt werden. Alle Teile müssen in dem gleichen Projekt sein!
Die folgenden Listings zeigen ein Beispiel einer aufgeteilten Klasse mit partieller Methode und partiellem Property sowie einem partieller Indexer.
Der erste Codeausschnitt zeigt den ersten Teil der partiellen Klasse nur mit Definitionen von Property ID, Indexer und Print():
using System.Text.Json.Serialization;
namespace NET9_Console.CS13;
/// <summary>
/// Erster Teil der partiellen Klasse nur mit Definitionen
/// </summary>
public partial class PersonWithAutoID
{
// NEU: Partielles Property --> kein "Convert to Full Property"
public partial int ID { get; set; }
// NEU: Partieller Indexer
public partial string this[int index] { get; }
// "Normales Property"
public string Name { get; set; }
// Partielle Methode (gab es vorher schon)
public partial void Print();
}
Im zweiten Teil der partiellen Klasse werden Getter und Setter für ID und den Indexer sowie die Methode Print() implementiert:
/// <summary>
/// Implementierung der Getter und Setter für ID, der Getter für den Indexer sowie die Methode Print()
/// </summary>
public partial class PersonWithAutoID
{
int counter = 0;
// Implementierung des Partial Property
private int iD;
public partial int ID
{
get
{
if (iD == 0) iD = ++counter;
return iD;
}
set
{
if (ID > 0) throw new ApplicationException("ID ist bereits gesetzt");
iD = value;
}
}
// Implementierung des Partial Indexer
public partial string this[int index]
{
get
{
return index switch
{
0 => ID.ToString(),
1 => Name,
_ => throw new IndexOutOfRangeException()
};
}
}
// Implementierung der Partial Method
public partial void Print()
{
Console.WriteLine($"{this.ID}: {this.Name}");
}
}
Folgender Code implementiert den Nutzer der zusammengesetzten Klasse PersonWithAutoID:
/// <summary>
/// Client-Klasse für die Demo
/// </summary>
public class CS13_PartialPropertyAndIndexerDemoClient
{
public void Run()
{
CUI.Demo(nameof(CS13_PartialPropertyAndIndexerDemoClient));
CS13.PersonWithAutoID p = new() { Name = "Holger Schwichtenberg" };
p.Print(); // 1: Holger Schwichtenberg
CUI.H2("Versuch, die ID neu zu setzen, führt zum Fehler:");
try
{
p.ID = 42;
}
catch (Exception ex)
{
CUI.Error(ex); // System.ApplicationException: ID ist bereits gesetzt
}
CUI.Print($"Nutzung des Indexers: {p[0]}: {p[1]} ");
}
}
URL dieses Artikels:
https://www.heise.de/-10237499
Links in diesem Artikel:
[1] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock)
Die Programmiersprache C# 13.0 ist zusammen mit Visual Studio 2022 Version 17.12 und .NET 9.0 am 12. November 2024 erschienen.
Das neue C# 13.0 unterstützt Microsoft offiziell erst ab .NET 9.0 ("C# 13.0 is supported only on .NET 9 and newer vesions.").
Man kann allerdings die meisten Sprachfeatures aus C# auch in älteren .NET-Versionen einschließlich .NET Framework, .NET Core und Xamarin nutzen. Dazu muss man die verwendete Compilerversion per Tag <LangVersion> in der Projektdatei (.csproj) auf "13.0" erhöhen.
<LangVersion>13.0</LangVersion>
Damit Sprachfeatures auch in Versionen vor .NET 9.0 funktionieren, dürfen sie keine Abhängigkeit von in .NET 9.0 eingeführten Basisbibliotheksklassen haben. Sofern man <LangVersion>latest</LangVersion> in der Projektdatei setzt, sind in älteren Versionen folgende neuen Sprachfeatures von C# 13.0 möglich:
ref struct, außer der Verwendung als Typargument\eZu beachten ist aber, dass es für den Einsatz der neuen Sprachfeatures in .NET-Versionen vor 9.0 keinen technischen Support von Microsoft gibt, man also bei Problemen nicht den Support-Vertrag nutzen kann, um Microsoft um Hilfe zu ersuchen. Dennoch ist der Einsatz höherer C#-Versionen in älteren .NET-Projekten in einigen Unternehmen gängige und problemlose Praxis.
In C# 13.0 sind folgende neue Sprachfeatures erschienen, die ich in den kommenden Wochen in dieser Blogserie besprechen werde:
\e für ANSI/VT100 Terminal Control Escape Sequences,params,Threading.Lock für lock-Anweisungen undref structs (auf Stack).Ein weiteres Sprachfeature ist in C# 13.0 in experimenteller Form enthalten: halbautomatische Properties mit dem neuen Schlüsselwort field. Dieses Schlüsselwort ist nur verfügbar, wenn man in einer Projektdatei entweder <EnablePreviewFeatures>True</EnablePreviewFeatures> oder <LangVersion>preview</LangVersion> setzt.
Folgende Sprachfeatures waren für C# 13.0 geplant und zum Teil schon als Prototyp verfügbar, wurden aber dann auf C# 14.0 vertagt [1], das im November 2025 erscheinen soll :
(int x, string y) = default statt (default, default)Array, Span<T> und ReadOnlySpan<T>extensioneinführen.Es gibt einige wenige Breaking Changes [2] im Verhalten des Compilers in C# 13.0 gegenüber C# 12.0. Dabei handelt es sich jedoch um Sonderfälle von geringer Bedeutung, beispielsweise das Verbot der Annotation [InlineArray] auf record struct).
URL dieses Artikels:
https://www.heise.de/-10217343
Links in diesem Artikel:
[1] https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md
[2] https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/breaking-changes/compiler%20breaking%20changes%20-%20dotnet%209
[3] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: TippaPatt/Shutterstock)
.NET 9.0 ist eine Version mit Standard-Term-Support (STS) für 18 Monate. Für einige Bibliotheken ist der Support aber deutlich kürzer.
Während die vorherige, im November 2023 erschiene Version 8.0 noch 36 Monate Support erhalten hat und daher noch bis zum November 2026 mit Updates versorgt wird, bietet Microsoft Aktualisierungen und technische Hilfe für .NET 9.0 für die Dauer von 18 Monaten, also nur bis Mai 2026 an.
(Bild: Microsoft)
Für einige von Microsoft veröffentlichte .NET-NuGet-Pakete, die nicht Teil des .NET-SDKs sind, gilt eine andere Support-Richtlinie.
Das betrifft folgende Paketfamilien:
Für diese Pakete gilt:
Die Liste der betroffenen NuGet-Pakete findet man auf der Seite zu den Extensions [1].
(Bild: Microsoft [2])
URL dieses Artikels:
https://www.heise.de/-10215755
Links in diesem Artikel:
[1] https://dotnet.microsoft.com/en-us/platform/support/policy/extensions
[2] https://dotnet.microsoft.com/en-us/platform/support/policy/extensions
[3] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: Pincasso/Shutterstock.com)
Auch für das aktuelle .NET-Release wird der Dotnet-Doktor-Blog die Neuerungen in einer Artikelserie detailliert beschreiben.
Mit diesem Beitrag beginne ich die neue Blogserie zu .NET 9.0. Wie im letzten Jahr zu .NET 8.0 [1] werde ich in zahlreichen kleineren Beiträgen die Neuerungen in .NET 9.0 vorstellen.
.NET 9.0 steht seit dem 12. November 2024 auf der Downloadseite [2] kostenfrei zur Verfügung. Für .NET 9.0 benötigen Entwicklerinnen und Entwickler die Entwicklungsumgebungen Visual Studio 2022 [3] mindestens in der Version 17.12.
Entwickelt wurde .NET 9.0 in den letzten 12 Monaten. Seitdem hat Microsoft sieben Preview-Versionen und zwei Release-Candidate-Versionen veröffentlicht, über ich für heise developer jeweils berichtete.
Wie schon bei .NET 6.0/C# 10.0 und .NET 7.0/C# 11.0 sowie .NET 8.0/C# 12.0 verwendet Microsoft an einigen Stellen eine Schreibweise ohne ".0" (.NET 9/C# 13) und an anderen mit ".0" (.NET 9.0/C# 13.0). Ich werde einheitlich die Schreibweise mit ".0" verwenden, wie es auf der Downloadseite [4] steht.
(Bild: Microsoft [5])
Meine Serie wird in den kommenden Wochen und Monaten über diese Aspekte von .NET 9.0 berichten:
Meine Beiträge erheben dabei nicht den Anspruch, die Dokumentation zu ersetzen oder zu überbieten. Leserinnen und Leser können meine Beiträge als Impulsgeber verstehen, sich zu entscheiden, ob eine Neuerung für ihre Anwendungsfälle Sinn ergibt und sie sich damit dann näher beschäftigen wollen.
Ich werde die Beiträge der Serie jeweils so weit im Voraus schreiben, dass eine wöchentliche Veröffentlichung gewährleistet ist. Aufgrund von redaktionellen Engpässen kann es dennoch vorkommen, dass einmal eine Woche kein Beitrag erscheint.
URL dieses Artikels:
https://www.heise.de/-10215673
Links in diesem Artikel:
[1] https://www.heise.de/blog/Neu-in-NET-8-0-1-Start-der-neuen-Blogserie-9574680.html
[2] https://dotnet.microsoft.com/en-us/download/dotnet/9.0
[3] https://visualstudio.microsoft.com/
[4] https://dotnet.microsoft.com/en-us/download/dotnet/9.0
[5] https://dotnet.microsoft.com/en-us/download/dotnet/9.0
[6] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: jakkaje879/Shutterstock.com)
Die Bücher des Bloggers Dotnet-Doktor sind passend zum Release avon.NET 9.0 auf dem aktuellen Stand.
Pünktlich zum Release von .NET 9.0 [1] ist es mir auch dieses Jahr wieder gelungen, dass meine .NET-Bücher auf dem RTM-Stand (Release to Manufacturing) verfügbar sind:
Die Bücher gibt es in gedruckter Form (Print-on-Demand), im PDF-Format und als Kindle-E-Book.
(Bild: IT-Visions.de [6])
URL dieses Artikels:
https://www.heise.de/-10032056
Links in diesem Artikel:
[1] https://www.heise.de/news/Microsoft-NET-9-0-bringt-Breaking-Changes-und-neue-KI-Bibliothek-10031831.html
[2] https://it-visions.de/buch/N9U
[3] https://it-visions.de/buch/CSC13
[4] https://it-visions.de/buch/EFC13
[5] https://it-visions.de/buch/BLA90
[6] http://www.it-visions.de/NET9buecher
[7] https://net.bettercode.eu/?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[8] https://net.bettercode.eu/index.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link#programm
[9] https://net.bettercode.eu/tickets.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[10] mailto:mdo@ix.de
Copyright © 2024 Heise Medien
(Bild: erstellt mit KI (Dall-E) von iX-Redaktion)
Die umfangreiche Serie mit Blogbeiträgen zu .NET 8.0 und den Neuerungen in C# 12 geht zwei Monate vor dem Release von .NET 9.0 zu Ende.
In den letzten 40 Wochen habe ich Ihnen jede Woche ein neues Feature aus .NET 8.0 vorgestellt. Es gab kleinere und größere Neuigkeiten in der Programmiersprache C#, der .NET-Basisklassenbibliothek und dem .NET Software Development Kit (SDK).
Auch wenn ich nicht alle neuen Features vorgestellt habe, möchte ich diese Serie nun enden lassen und mich in den kommenden Wochen darauf konzentrieren, meine Fachbücher zu C# [1], Blazor [2] und Entity Framework Core [3] auf den Stand von .NET 9.0 zu bringen.
.NET 9.0 ist seit dieser Woche im Stadium "Release Candidate 2" [4] und mit einer "Go-Live"-Lizenz ausgestattet. Die fertige Version soll am 12. November 2024 erscheinen. Die oben genannten Bücher will ich bis dahin auf dem aktuellen Stand haben, sodass diese wie in den Vorjahren pünktlich zum Erscheinungstermin verfügbar sind.
Aktuell gibt es von mir das Buch .NET 9.0 Update [8], das auf dem Stand des Release Candidate 2 ist und auf 170 Seiten die Neuerungen gegenüber .NET 8.0 beschreibt.
.NET 8.0 hat noch Long-Term Support bis zum November 2026. Es besteht also kein Zwang, auf .NET 9.0 zu wechseln. Das kommende .NET-Release wird mit Standard-Term Support von Microsoft von November 2024 bis Mai 2026 mit Updates versorgt werden. Zwischenzeitlich ist für November 2025 dann .NET 10.0 geplant.
Ab Dezember plane ich eine neue Blogserie mit den Neuerungen aus .NET 9.0.
URL dieses Artikels:
https://www.heise.de/-9977510
Links in diesem Artikel:
[1] https://it-visions.de/Csharpbuch
[2] https://it-visions.de/Blazorbuch
[3] https://it-visions.de/EFCorebuch
[4] https://www.heise.de/news/Jetzt-schon-einsetzen-NET-9-0-Release-Candidate-2-mit-Go-Live-Lizenz-9974342.html
[5] https://net.bettercode.eu/?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[6] https://net.bettercode.eu/index.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link#programm
[7] https://net.bettercode.eu/tickets.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[8] https://www.it-visions.de/buch/n9U
[9] mailto:rme@ix.de
Copyright © 2024 Heise Medien