Neu in .NET 7 [4]: Zusätzlicher Scope mit File-local Types in C# 11
Das aktuelle Release von Microsofts Programmiersprache C# führt mit file einen neuen Scope für Klassen, Strukturen, Interfaces und Co ein.
(Bild: Alex SG/Shutterstock.com)
- Dr. Holger Schwichtenberg
C# 11 führt für .NET-Typen die Sichtbarkeit (Scope) file
zusätzlich zu den bisher bekannten public
, private
, protected
, internal
, protected internal
und private protected
ein.
Mit dem neuen Schlüsselwort file
versehene Schnittstellen, Klassen, Strukturen, Enumerationen, Delegates und Records sind nur innerhalb der Datei sichtbar, in der sie deklariert werden. Für eingebettete Typen ist file
nicht erlaubt.
Auf den ersten Blick widerspricht die Sichtbarkeit file
den von Microsoft seit Jahren gepredigten Best Practices, pro Datei nur einen einzigen Typ zu deklarieren. Wenn man diesen einen Typ dann mit dem Zusatz file
ausstattet, ist er außerhalb der Datei nicht sichtbar und damit überflüssig.
In der Praxis kann es aber durchaus sinnvoll sein, mehrere kleinere Typen in einer Datei zu deklarieren, etwa weil eine Klasse eine eigene persönliche, nur für diese Klasse geltende Datenstruktur in Form einer anderen Klasse oder eines Record-Typs erhält. Microsoft hat den Scope file
für die Source Generators eingeführt: Sie sollen Hilfsklassen erzeugen können, ohne in Konflikt mit anderen Generatoren zu geraten.
Beispiel für den Einsatz
Als Beispiel dient Code, der den Inhalt einer Datei zeigt, die drei Typen deklariert:
- Schnittstelle
IPerson
mit Scopepublic
- Klasse
Person
, dieIPerson
implementiert, mit Scopefile
- Klasse
PersonManager
mit Scopepublic
Der Code zeigt: PersonManager
kann durchaus eine Instanz von Person
an die Außenwelt (Code in anderen Dateien) liefern, denn diese können die Instanz über Schnittstelle IPerson
verwenden. Die Außenwelt kann aber keine Instanz von Person
hineinreichen, weil sie diese Klasse nicht kennt.
namespace NET7Console;
public interface IPerson
{
public int ID { get; set; }
public string? Name { get; set; }
public string GetInfo();
}
file class Person : IPerson
{
public int ID { get; set; }
public string? Name { get; set; }
public string GetInfo() =>
$"{this.GetType().FullName} {this.ID}: {this.Name}";
}
public class PersonManager
{
public int ID { get; set; }
public string? Name { get; set; }
public string GetInfoFromTestPerson()
{
Person p = new();
return p.GetInfo();
}
public IPerson CreatePerson()
{
return new Person();
}
// Nicht möglich: File-local type 'Person' cannot be used
// in a member signature in non-file-local type 'PersonManager'.
//public int GetInfo(Person p)
//{
// return p.GetInfo();
//}
}
Typen mit file
-Scope bekommen einen vom Compiler vergebenen Namenszusatz, der sie eindeutig macht. Der Namensaufbau ist: <Dateiname>HEX-ZAHL__Typname
.
Ein Typ mit Scope file
kann einen anderen Typen, der übergeordnet sichtbar ist, verdecken. Beispiel: Wenn es neben einer Klasse Person
in der Datei Person.cs, die internal
oder public
ist, noch einen Klasse file class Person
in Test.cs gibt, ist innerhalb dieser Datei Test.cs der Typ Person
aus Person.cs nicht sichtbar.
(rme)