Neu in .NET 7 [6]: Required Members mit C# 11.0

Ein neues Schlüsselwort für Microsofts Programmiersprache C# legt fest, dass Properties oder Felder zwingend gesetzt werden müssen.

In Pocket speichern vorlesen Druckansicht 5 Kommentare lesen

(Bild: heise online)

Lesezeit: 2 Min.
Von
  • Dr. Holger Schwichtenberg

Das neue C# bringt das neue Schlüsselwort required für Fields und Properties. Wenn ein Datenmitglied einer Klasse diesen Zusatz erhält, dann ist zwingend erforderlich, dass dieses Datenmitglied entweder im Konstruktor oder Objekt-Initialisierer vom Nutzer der Klasse gesetzt wird. Ein Konstruktor ist mit [SetsRequiredMembers] annotierbar, was dem Compiler anzeigt, dass er alle erforderlichen Mitglieder belegt.

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.

Der Zusatz required ist erlaubt bei Datenmitgliedern in Klassen, Strukturen und Record-Typen, aber nicht in Schnittstellen.

Die folgende Klasse deklariert ein Field und zwei Properties mit required sowie eine weitere Property ohne diesen Zusatz. Zudem gibt es neben dem parameterlosen Konstruktor zwei weitere Konstruktoren mit Parametern, die beide mit [SetsRequiredMembers] annotiert sind; allerdings setzt einer von beiden alle drei der erforderlichen Mitglieder auf belegt.

Der Code kompiliert auch, wenn [SetsRequiredMembers] gar nicht alle erforderlichen Mitglieder setzt. Es gibt auch keine Warnung! Das heißt: Der Compiler verlässt sich auf die Angabe [SetsRequiredMembers] im Code. Der ursprüngliche Plan, dass der Compiler es validiert, wurde verworfen. Ebenso gab es den Plan, dass man einzelne Mitglieder ein- und ausschließen kann. Auch dies ist Stand C# 11.0 nicht möglich. Zitat Microsoft:

"An earlier version of this proposal had a larger metalanguage around initialization, allowing adding and removing individual required members from a constructor, as well as validation that the constructor was setting all required members. This was deemed too complex for the initial release, and removed. We can look at adding more complex contracts and modifications as a later feature."

public class Consultant
{
 public Consultant() { }
 
 [SetsRequiredMembers]
 public Consultant(int id, string name) => 
   (ID, Name) = (id, name);
 [SetsRequiredMembers]
 public Consultant(int id, string name, DateTime created) => 
   (ID, Name, Created) = (id, name, created);
 
 public required int ID; // Required Field
 public required string Name { get; init; } // Required Property
 public required DateTime Created { get; init; } 
   = DateTime.Now; // Required Property
 
 public string? City { get; set; } // nicht "required"!
}

Diese Klasse ist nun wie folgt instanziierbar:

// 1. Aufruf des Konstruktors mit den drei erforderlichen Angaben
var p1 = new Consultant(1, "Dr. Holger Schwichtenberg",
                        DateTime.Now);

// 2. Aufruf des Konstruktors mit nur zwei der drei Angaben
var p2 = new Consultant(2, "Dr. Joachim Fuchs");

// 3. Aufruf der parameterlosen Initialisierung aller drei
// Angaben im Objekt-Initialisierer
var p3 = new Consultant() { ID = 2, Name = 
  "Dr.habil. Klaus Schmaranz", Created = DateTime.Now  };

Nicht erlaubt ist hingegen:

  • Parameterloser Konstruktor ohne Objekt-Initialisierer:
  • Parameterloser Konstruktor mit unvollständigem Objekt-Initialisierer:

Das Beispiel zeigt auch: Es reicht nicht, dass die Property Created eine Standardwertzuweisung in der Klasse besitzt. Der Aufrufer muss trotzdem Created belegen.

Visual Studio zeigt in den Tooltips deutlich an, wenn es erforderlich ist, ein Mitglied zu setzen:

(rme)