FreshRSS

🔒
❌ Über FreshRSS
Es gibt neue verfügbare Artikel. Klicken Sie, um die Seite zu aktualisieren.
Vor vorgesternDeveloper-Blog - Der Dotnet-Doktor ff.org

[unable to retrieve full-text content]

  • 03. April 2025 um 23:30

Neu in .NET 9.0 [14]: Multiplikation großer Zahlen mit BigMul()

Von Heise

(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

Adblock test (Why?)

  • 28. März 2025 um 10:48

Neu in .NET 9.0 [12]: GUID-Version 7 mit CreateVersion7()

Von Heise

(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}");
 }
}

Die Ausgabe zu dem Listing zeigt, dass die GUIDs in Version 7 sich aufgrund des enthaltenen Timestamps ähnlich sind.

(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

Adblock test (Why?)

  • 14. März 2025 um 17:03

Neu in .NET 9.0 [11]: Neue Möglichkeiten für ref struct in C# 13.0

Von Heise

(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:

  • Schnittstellen implementieren. Allerdings gilt die Einschränkung, dass die Struktur nicht in den Schnittstellentyp konvertiert werden kann, da der Compiler intern dafür ein Boxing machen müsste.
  • als Typargument genutzt werden. Allerdings muss man dazu den generischen Typ beziehungsweise die generische Methode where T : allows ref struct verwenden.
  • in Iteratoren mit yield verwendet werden. Allerdings darf die Struktur nicht länger leben als der aktuelle Durchlauf des Iterator.
  • in asynchronen Methoden, die 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

Adblock test (Why?)

  • 07. März 2025 um 11:44

Neu in .NET 9.0 [14]: Multiplikation großer Zahlen mit BigMul()

Von Dr. Holger Schwichtenberg

(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

Adblock test (Why?)

  • 28. März 2025 um 10:48

Neu in .NET 9.0 [13]: Mehr Genauigkeit für TimeSpan

Von Dr. Holger Schwichtenberg

(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
 }
 
}

Der zweite Wert ist in der alten Form ungenau, aber in der neuen genau.

(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

Adblock test (Why?)

  • 21. März 2025 um 15:14

Neu in .NET 9.0 [12]: GUID-Version 7 mit CreateVersion7()

Von Dr. Holger Schwichtenberg

(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}");
 }
}

Die Ausgabe zu dem Listing zeigt, dass die GUIDs in Version 7 sich aufgrund des enthaltenen Timestamps ähnlich sind.

(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

Adblock test (Why?)

  • 14. März 2025 um 17:03

Neu in .NET 9.0 [11]: Neue Möglichkeiten für ref struct in C# 13.0

Von Dr. Holger Schwichtenberg

(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:

  • Schnittstellen implementieren. Allerdings gilt die Einschränkung, dass die Struktur nicht in den Schnittstellentyp konvertiert werden kann, da der Compiler intern dafür ein Boxing machen müsste.
  • als Typargument genutzt werden. Allerdings muss man dazu den generischen Typ beziehungsweise die generische Methode where T : allows ref struct verwenden.
  • in Iteratoren mit yield verwendet werden. Allerdings darf die Struktur nicht länger leben als der aktuelle Durchlauf des Iterator.
  • in asynchronen Methoden, die 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

Adblock test (Why?)

  • 07. März 2025 um 11:44

Neu in .NET 9.0 [10]: Neue Klasse für lock-Statements in C# 13.0

Von Dr. Holger Schwichtenberg
Straßenschild mit C# drauf.

(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

Adblock test (Why?)

  • 28. Februar 2025 um 10:07

Neu in .NET 9.0 [9]: Array-Initialisierung mit Index-Operator in C# 13.0

Von Dr. Holger Schwichtenberg

(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

Adblock test (Why?)

  • 21. Februar 2025 um 13:52

Neu in .NET 9.0 [8]: Generische Mengentypen bei variadischen Parametern in C#

Von Dr. Holger Schwichtenberg

(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>
  • Alle Klassen, die Collections.Generic.IEnumerable<T>implementieren
  • Span<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

Adblock test (Why?)

  • 14. Februar 2025 um 11:40

Neu in .NET 9.0 [7]: Prioritäten für Methodenüberladungen in C# 13.0

Von Dr. Holger Schwichtenberg

(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:

  • Je höher die in der Annotation angegebene Zahl ist, umso höher ist die Priorität.
  • Die Standardpriorität ist 0.
  • Eine Angabe einer negativen Zahl ist möglich, um die Priorität unter den Standard zu senken.

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();
 }
 
}

Ausgabe des Listings

(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

Adblock test (Why?)

  • 07. Februar 2025 um 12:13

Kostenloser Vortrag zu den Neuerungen in .NET 9.0 und C# 13.0

Von Dr. Holger Schwichtenberg

(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:

  • Neuerungen in der Sprachsyntax von C# 13.0
  • Neuerungen in der .NET 9.0-Basisklassenbibliothek
  • Ausgewählte Neuerungen in ASP.NET Core, Blazor, WPF und Windows Forms in .NET 9.0

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

Adblock test (Why?)

  • 30. Januar 2025 um 10:41

Neu in .NET 9.0 [6]: Neues Escape-Zeichen für Konsolenausgaben

Von Dr. Holger Schwichtenberg

(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");

Die Ausgabe der beiden vorherigen Listings sieht gleich aus.

(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

Adblock test (Why?)

  • 24. Januar 2025 um 12:42

Neu in .NET 9.0 [4]: Partielle Properties und partielle Indexer in C# 13.0

Von Dr. Holger Schwichtenberg

(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 Neuerungen in Codebeispielen

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

Adblock test (Why?)

  • 13. Januar 2025 um 14:30

Neu in .NET 9.0 [3]: Features in der Programmiersprache C# 13.0

Von Dr. Holger Schwichtenberg

(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.").

C# 13.0 in älteren .NET-Versionen

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:

  • Partielle Properties und partielle Indexer
  • Generische Mengen in Verbindung mit dem Schlüsselwort params
  • Neuerungen für ref struct, außer der Verwendung als Typargument
  • Escape-Zeichen \e

Zu 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.

Stabile neue Sprachfeatures in C# 13.0

In C# 13.0 sind folgende neue Sprachfeatures erschienen, die ich in den kommenden Wochen in dieser Blogserie besprechen werde:

  • Partielle Properties und partielle Indexer,
  • neues ESCAPE-Zeichen \e für ANSI/VT100 Terminal Control Escape Sequences,
  • Prioritäten für Methodenüberladungen,
  • Generische Mengentypen bei params,
  • Objekt-Initialisierung mit Index-Operator vom Ende,
  • Neue Klasse Threading.Lock für lock-Anweisungen und
  • Erweiterungen für ref structs (auf Stack).

Experimentelles Sprachfeature in C# 13.0

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.

Vertagte neue Sprachfeatures

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 :

  • Tupel-Dekonstruktion(int x, string y) = default statt (default, default)
  • Automatische Konvertierung zwischen Array, Span<T> und ReadOnlySpan<T>
  • Extensions: eine weiterentwickelte, generalisierte Form der Extension Methods, bei der man nicht nur Instanzmethoden, sondern Methoden und Properties sowohl auf Instanz- als auch Klassenebene ("static") ergänzen kann. Dazu will Microsoft das neue Schlüsselwort extensioneinführen.

Breaking Changes in C# 13.0

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

Adblock test (Why?)

  • 03. Januar 2025 um 08:30

Neu in .NET 9.0 [2]: Support für .NET 9.0

Von Dr. Holger Schwichtenberg
Kalender, physisch – und mit Smartphone

(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.

Microsoft unterscheidet bei den Support-Zyklen für das moderne .NET zwischen STS- und LTS-Releases.

(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:

  • Extensions.*, zum Beispiel Microsoft.Extensions.Http.Resilience und Microsoft.Extensions.Telemetry
  • AspNetCore.*, zum Beispiel Microsoft.AspNetCore.Testing und Microsoft.AspNetCore.Diagnostics.Middleware

Für diese Pakete gilt:

  • Es kann jeden Monat ein neues Minor Release geben (9.1, 9.2, 9.3, ...).
  • Es gibt immer nur Support für das aktuellste Release.
  • Die Regeln des Semantic Versioning befolgt Microsoft nicht streng.

Die Liste der betroffenen NuGet-Pakete findet man auf der Seite zu den Extensions [1].

Microsoft erläutert den abweichenden Support für die .NET Platform Extensions.

(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

Adblock test (Why?)

  • 27. Dezember 2024 um 08:30

Neu in .NET 9.0 [1]: Start der neuen Blogserie

Von Holger Schwichtenberg

(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.

Offizieller Name

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.

Die Downloadseite (Stand 11.12.2024) verwendet einheitlich die Schreibweise .NET 9.0

(Bild: Microsoft [5])

Inhalt der Blogserie

Meine Serie wird in den kommenden Wochen und Monaten über diese Aspekte von .NET 9.0 berichten:

  • Neue Sprachfeatures in der Programmiersprache C# 13.0
  • Neue Funktionen im Software Development Kit (SDK) in .NET 9.0
  • Neue und erweiterte Klassen in der .NET 9.0-Klassenbibliothek:

Ziele der Blogserie

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

Adblock test (Why?)

  • 20. Dezember 2024 um 08:56

Fachbücher zu .NET 9.0, C# 13.0, Entity Framework Core 9.0 und Blazor 9.0

Von Dr. Holger Schwichtenberg

(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.

Abbildung der Buchcover

(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

Adblock test (Why?)

  • 13. November 2024 um 19:04

Ende der .NET-8.0-Serie – NET 9.0 kommt bald​

Von Dr. Holger Schwichtenberg
Zwei Kugeln mit den Ziffern 8 und 9

(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.

Keine Eile beim Wechsel

.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

Adblock test (Why?)

  • 11. Oktober 2024 um 11:26
❌