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

C# 13.0 bietet neben partiellen Klassen und Methoden jetzt auch die lang erwartete Umsetzung fĂĽr partielle Properties und Indexer.

vorlesen Druckansicht 6 Kommentare lesen

(Bild: Pincasso/Shutterstock)

Lesezeit: 2 Min.
Von
  • Dr. Holger Schwichtenberg

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.

Der Dotnet-Doktor – Holger Schwichtenberg
Der Dotnet-Doktor – Holger Schwichtenberg

Dr. Holger Schwichtenberg ist technischer Leiter des Expertennetzwerks www.IT-Visions.de, das mit 53 renommierten Experten zahlreiche mittlere und große Unternehmen durch Beratungen und Schulungen sowie bei der Softwareentwicklung unterstützt. Durch seine Auftritte auf zahlreichen nationalen und internationalen Fachkonferenzen sowie mehr als 90 Fachbücher und mehr als 1500 Fachartikel gehört Holger Schwichtenberg zu den bekanntesten Experten für .NET und Webtechniken in Deutschland.

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.

Videos by heise

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

(rme)