Die Bedeutung qualifizierter Namen in C♯
Das folgende Programm wurde schon behandelt. Seine Ausgabe ist der Wert des Wertnamens »global::System.Int32.MaxValue«.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Int32.MaxValue ); }}global::System.Console.Out
2147483647
Im folgenden sollen nun solche Namen, wie beispielsweise der Wertname »global::System.Int32.MaxValue«, näher beschrieben werden.
Qualifizieren
„Qualifizieren“ bedeutet soviel wie: „näher bestimmen“.
Im qualifizierten Namen »global::System.Int32.MaxValue« wird der am Ende stehende Bezeichner »MaxValue« durch den vorangestellten Text »global::System.Int32.« näher bestimmt („qualifiziert“). So kann er von anderen Namen, wie beispielsweise »global::System.Decimal.MaxValue«, die auch mit »MaxValue« enden, unterschieden werden. Solche langen Namen sind hilfreich, wenn in großen Programmen mehrere ähnliche Namen unterschieden werden sollen, ähnlich wie man in großen Gruppen von Personen zur Unterscheidung der Personen bei Gleichheit zweier Nachnamen noch die Vornamen zur Unterscheidung heranziehen kann.
- Vergleich von C♯ -Namen und Personenbezeichnungen
global::System. Int32. MaxValue Prof. Dr. Müller
Die Bedeutung des Punktes ».«
Der Punkt ».« drückt in qualifizierten Namen in der Regel aus, daß das Rechtsstehende als in dem Linksstehenden „enthalten“ angesehen wird.
Daher nennen wir etwas, das links von einem Punkt steht oder stehen kann, auch ein Verzeichnis (man denke an ein Verzeichnis eines Datenträgers), und etwas, das rechts von einem Punkt stehen kann, einen Eintrag.
Das Verzeichnis »global::System.Int32« enthält also den Eintrag »MaxValue«. (»»global::System.Int32«« enthält auch noch andere Einträge, wie beispielsweise »MinValue«.)
Das Verzeichnis »global::System« enthält den Eintrag »Int32«.
Man kann sich vorstellen, daß es in C♯ so viele Namen gibt, daß Typen herangezogen werden, um sie übersichtlich abzulegen, so wie man Gegenstände in verschiedenen Schubladen ablegt.
- Das Ineinanderenthaltensein bei »global::System.Int32.MaxValue«
.----------------------------------------------------------.
| global::System |
| .------------------------------------------------------. |
| | Int32 | |
| | .--------------------------------------------------. | |
| | | MaxValue | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
'----------------------------------------------------------'- Das Ineinanderenthaltensein der bisher vorgestellten Namen
.----------------------------------------------------------.
| global::System |
| .------------------------------------------------------. |
| | Int32 | |
| | .--------------------------------------------------. | |
| | | MaxValue | | |
| | | MinValue | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Decimal | |
| | .--------------------------------------------------. | |
| | | MaxValue | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Math | |
| | .--------------------------------------------------. | |
| | | PI | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
'----------------------------------------------------------'
Wertnamen
Der Name »global::System.Math.PI« steht, ähnlich wie ein Literal, für einen bestimmten Wert. Daher nennen wir ihn auch einen Wertnamen.
Konstanten
Wertnamen werden auch oft als Konstanten bezeichnet.
Wir können »global::System.Math.PI« also auch als eine Konstante bezeichnen.
- Das Ineinanderenthaltensein der bisher vorgestellten Namen
.----------------------------------------------------------.
| global::System |
| .------------------------------------------------------. |
| | Int32 | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | | Konstante "MinValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Decimal | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Math | |
| | .--------------------------------------------------. | |
| | | Konstante "PI" | | |
| | | Konstante "E" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
'----------------------------------------------------------'
Eigentliche Namen
Der Bezeichner am Ende eines qualifizierten Namens bestimmt die Bedeutung des ganzen Namens. Beispielsweise ist »global::System.Math.PI« die Kreiszahl ‹ π › („Pi“) und »global::System.Math.E« die Eulersche Zahl ‹ e ›. Das davorstehende Verzeichnis gibt nur einen Zusammenhang (Kontext) an, um Mißverständnisse zu vermeiden, entscheidend ist aber der Bezeichner am Ende. So ist es in manchen Fällen auch möglich, ein Verzeichnis wegzulassen, aber der Bezeichner am Ende muß immer genannt werden, um sich auf eine bestimmte Konstante zu beziehen.
Der Bezeichner am Ende eines qualifizierten Namens bestimmt, wofür der ganze Name steht. Daher nennen wir den Bezeichner am Ende eines qualifizierten Namens auch den eigentlichen Namen.
Der eigentliche Name in »global::System.Math.PI« ist also beispielsweise »PI«.
Beim mündlichen Bezug auf einen Namen reicht es oft, nur den eigentlichen Namen oder eine Teil vom Ende des Namens auszusprechen, wenn das Davorstehende sich aus dem Zusammenhang ergibt. So kann der Name »global::System.Math.PI« also oft einfach als “pi ” oder “math pi ” ausgesprochen werden.
- Zitat *
- “The nameof expression only retrieves the final identifier, even if you use more explicit dotted names.”
- https://msdn.microsoft.com/en-us/magazine/dn802602.aspx
Typen
Verzeichnisse, die Wertnamen direkt enthalten (wie »global::System.Int32«), werden in C♯ auch noch einmal durch eine besondere Bezeichnung gewürdigt: Sie werden als Typen bezeichnet.
Man kann sich solch einen Typ als ein Verzeichnis für Wertnamen vorstellen.
- Das Ineinanderenthaltensein der bisher vorgestellten Namen
.----------------------------------------------------------.
| global::System |
| .------------------------------------------------------. |
| | Typ "Int32" | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | | Konstante "MinValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Typ "Decimal" | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Typ "Math" | |
| | .--------------------------------------------------. | |
| | | Konstante "PI" | | |
| | | Konstante "E" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
'----------------------------------------------------------'
Strukturen und Klassen
Man unterscheidet in C♯ zwischen Strukturtypen und Klassentypen. Strukturtypen werden meist nur kurz Strukturen genannt. Klassentypen werden oft Klassen genannt. Strukturen sind Werttypen während Klassen Referenztypen sind.
Die Unterschiede zwischen Strukturen und Klassen sowie zwischen Werttypen und Referenztypen sind für uns derzeit noch nicht wichtig. Sie werden erst später behandelt werden. Dennoch geben wir schon jetzt oft an, ob ein bestimmter Typ eine Struktur oder eine Klasse ist, damit man sich von Anfang an an die richtigen Bezeichnungen gewöhnt.
- Das Ineinanderenthaltensein der bisher vorgestellten Namen
.----------------------------------------------------------.
| global::System |
| .------------------------------------------------------. |
| | Struktur "Int32" | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | | Konstante "MinValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Struktur "Decimal" | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Klasse "Math" | |
| | .--------------------------------------------------. | |
| | | Konstante "PI" | | |
| | | Konstante "E" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
'----------------------------------------------------------'- Das Typsystem von C♯
Typen |
.---------------'---------------.
| | Referenztypen Werttypen | | Klassen Strukturen global::System.Math global::System.Int32
global::System.Double
global::System.Decimal
Groß- und Kleinschreibung
Einträge eines Typs werden normalerweise mit großem Anfangsbuchstaben und kleinem Rest geschrieben, wobei Anfänge englischer Wörter jedoch ebenfalls mit einem Großbuchstaben hervorgehoben werden. Ein Beispiel für diese Schreibweise ist »MaxValue«. Bei Abkürzungen werden ebenfalls die Anfangsbuchstaben der abgekürzten Wörter groß geschrieben, wie beispielsweise bei »DBNull« (»global::System.Convert.DBNull«). Diese Schreibweise wird manchmal auch Pascal-Schreibweise genannt.
Ausnahmen Das Wort »PI« der Klasse »global::System.Math« ist eine Ausnahme von dieser Regel. Es gibt in noch einige weitere Ausnahmen, in denen mehr Großschreibung oder sogar Grundstriche verwendet werden, wie beispielsweise »METHODS_TO_SKIP« (»global::System.Diagnostics.StackTrace.METHODS_TO_SKIP«).
Eigentliche Namen von Typen
Den eigentliche Name eines Typs findet man im qualifizierten Namen des Typs hinter dem letzten Punkt. So ist der eigentliche Name von »global::System.Int32« der Name »Int32«.
Eigentliche Namen von Typen, wie beispielsweise »Int32«, werden in C♯ in Pascal -Schreibweise geschrieben.
Typen als Ordnungssystem
Um verschiedene Wertnamen auch bei Gleichheit ihres eigentlichen Namens noch unterscheiden und übersichtlich ordnen zu können, werden die Wertnamen in verschiedene Typen eingeordnet. So ist es dann beispielsweise möglich, zwischen den Feldern »global::System.Int32.MaxValue« und »global::System.Decimal.MaxValue« zu unterscheiden.
Man kann die Typen als Schubladen ansehen, in welche Konstanten zur besseren Übersicht hineingelegt werden. Dabei werden Konstanten, die inhaltlich zusammengehören möglichst auch in einen gemeinsamen Typ eingeordnet, wie beispielsweise »global::System.Math.PI« und »global::System.Math.E« – die Kreiszahl ‹ π › und die Eulersche Zahl ‹ ℯ › werden beide als „mathematische“ Konstanten empfunden.
Namensräume
Um verschiedene Typen auch bei Gleichheit ihres eigentlichen Namens noch unterscheiden und übersichtlich ordnen zu können, können auch Typen wiederum in verschiedene Verzeichnisse eingeordnet werden, die in diesem Fall Namensräume genannt werden.
Im Falle des Typnamens »global::System.Int32« ist »Int32« der eigentliche Typname, und »global::System« ist ein Namensraum.
Der qualifizierte Name »global::System.Int32.MaxValue« enthält also einen Namensraum »global::System«, einen Typnamen »global::System.Int32« (beziehungsweise »Int32« als eigentlichen Typnamen) und schließlich einen Wertnamen »global::System.Int32.MaxValue« (beziehungsweise »MaxValue« als eigentlichen Wertnamen).
- Das Ineinanderenthaltensein der bisher vorgestellten Namen
.----------------------------------------------------------.
| Namensraum "global::System" |
| .------------------------------------------------------. |
| | Struktur "Int32" | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | | Konstante "MinValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Struktur "Decimal" | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Klasse "Math" | |
| | .--------------------------------------------------. | |
| | | Konstante "PI" | | |
| | | Konstante "E" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
'----------------------------------------------------------'
Der Namensraum »global::System« enthält viele Standardtypen der Programmiersprache C♯, also Typen, die Bestandteil der Programmiersprache von C♯ sind, im Gegensatz zu Typen, die als Teil von Erweiterungen verfügbar sind.
Die Namen von Namensräumen werden ebenfalls in der Pascal-Schreibweise geschrieben.
Verschachtelte Namensräume
Es ist auch möglich, daß ein Namensraum in einem anderen Namensraum eingetragen, also enthalten, ist. Beispielsweise ist der Namensraum »global::System.Text« im Namensraum »global::System« enthalten. Wir illustrieren dies in dem folgenden Programm mit der Ausgabe des Wertes der Konstanten »CharSize« aus der Klasse »UnicodeEncoding« aus dem Namensraum »Text« aus dem Namensraum »global::System«.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Text.UnicodeEncoding.CharSize ); }}global::System.Console.Out
2
- Das Ineinanderenthaltensein der bisher vorgestellten Namen
.----------------------------------------------------------.
| Namensraum "global::System" |
| .------------------------------------------------------. |
| | Struktur "Int32" | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | | Konstante "MinValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Struktur "Decimal" | |
| | .--------------------------------------------------. | |
| | | Konstante "MaxValue" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Klasse "Math" | |
| | .--------------------------------------------------. | |
| | | Konstante "PI" | | |
| | | Konstante "E" | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
| .------------------------------------------------------. |
| | Namensraum "Text" | |
| | .--------------------------------------------------. | |
| | | Klasse "UnicodeEncoding" | | |
| | | .----------------------------------------------. | | |
| | | | Konstante "CharSize" | | | |
| | | '----------------------------------------------' | | |
| | '--------------------------------------------------' | |
| '------------------------------------------------------' |
'----------------------------------------------------------'
Globale Namensräume
Unter einem globalen Namensraum verstehen wir einen Namensraum, der in keinem anderen Namensraum enthalten ist. »global::System« ist ein globaler Namensraum, während »global::System.Text« kein globaler Namensraum ist.
Durch Voranstellung von »global::« kann es sichergestellt werden, daß ein Namensraumname für einen globalen Namensraum steht, falls es einen globalen Namensraum dieses Namens gibt. (Das »global::« verlangt eigentlich nur, daß die Suche nach einem Namensraum des dahinterstehenden Namens bei den globalen Namensräumen beginnen soll.)
Mit »System« alleine könnte in einem C♯ -Programm auch etwas anderes bezeichnet werden, das dort »System« genannt wird, während »global::System« sich immer eindeutig auf den globalen Namensraum »global::System« bezieht.
In vielen Programm würde es zwar ausreichen, nur »System« zu schreiben, doch wenn ein Fragment aus solch einem Programm an eine andere Stelle kopiert wird, könnte es sein, daß es dann notwendig wird, an mehreren Stellen ein »global::« einzufügen. Wenn das »global::« von Anfang an da steht, ist das nicht nötig, und die Bedeutung des Fragmentes hängt weniger von seiner Umgebung ab.
Es ist einfacher »global::« in einem Programm überall automatisch zu entfernen (falls jemand sich dadurch gestört fühlt), als es umgekehrt an den richtigen Stellen hinzuzufügen. Deswegen wird es in diesem Kurs häufig verwendet, auch wenn es oft nicht nötig wäre.
Durch die häufige Wiederholung kann sich der Leser die Verwendung von »global::« so auch gut einprägen, um es dann bei Bedarf verwenden zu können.
Vollständig qualifizierte Namen
Namen, die mit einem globalen Namensraum beginnen, wie »global::System.Int32.MaxValue« sind vollständig bestimmt : noch genauer können sie nicht geschrieben werden (man kann keinen weiteren Bezeichner davor setzen).
Name, die mit einem globalen Namensraum beginnen, werden deswegen werden sie auch als vollständig qualifizierte Namen oder als maximal qualifizierte Namen bezeichnet. Ein vollständig qualifizierter Name ist ein Name, vor den keine weiteren Qualifikation mehr hinzugefügt werden können (um ihn noch näher zu bestimmen).
Namen, die nicht vollständig qualifiziert wird, können von dem Ort ihrer Verwendung abhängen und werden daher hier auch relative Namen genannt.
- Namen
qualifizierter Name qualifizierter Name Eigentlicher Name Gattung
(vollstaendig qualifizierter Name) (Bezeichner) global::System.Int32.MaxValue Int32.MAX_VALUE MaxValue Konstante
global::System.Decimal.MaxValue Decimal.MAX_VALUE MaxValue Konstante
global::System.Math.PI Math.PI PI Konstante
global::System.Math.E Math.E E Konstante global::System.Int32 Int32 Struktur
global::System.Decimal Decimal Struktur
global::System.Math Math Klasse global::System global::System Namensraum
global::System.Int32« ist also der vollständig qualifizierte Name der Struktur »Int32« aus dem Namensraum »global::System«.
»global::System.Int32.MaxValue« ist der vollständig qualifizierte Name der Konstanten »MaxValue« aus der Struktur »global::System.Int32«.
Ausdrücke
Konstanten, Typnamen und Namensräume sind Ausdrücke. Jedoch sind nur Konstante auch Wertausdrücke.
Ausdrücke für Namensräume und Typnamen können in diesem Teil des Kurses nur zur Qualifikation, also direkt links von einem Punkt verwendet werden.
Einfache Typen
Die Typen »int«, »double« und »decimal« werden als einfache Typen bezeichnet und mit einem kleinen Anfangsbuchstaben geschrieben.
Zu jedem einfachen Typ gehört ein Strukturtyp, und ein Ausdruck eines einfachen Typs kann auch als Ausdruck des zugehörigen Strukturtyps angesehen werden
- Die Typaliasse in C♯
Alias Typ int global::System.Int32
double global::System.Double
decimal global::System.Decimal string global::System.String
Der Typ »string« ist kein einfacher Typ, aber auch er kann als Alias eines anderen Typs angesehen werden, nämlich von »global::System.String«.
- Das Typsystem von C♯
Typen |
.----------------'----------------.
| |
nicht-einfache Typen |
| |
.--------------'--------------. |
| | |
Referenztypen Werttypen |
| | |
Klassen Strukturen einfache Typen global::System.Math global::System.Int32 = int
global::System.String global::System.Double = double
= string global::System.Decimal = decimal
Die folgenden beiden Beispielprogramme haben dieselbe Bedeutung und illustrieren, daß der einfache Typ »int« nur ein Alias für die Struktur »global::System.Int32« ist.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( int.MaxValue ); }}global::System.Console.Out
2147483647
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Int32.MaxValue ); }}global::System.Console.Out
2147483647
Da C♯ ausdrücklich erklärt, daß »123« ein int-Literal ist und Konstanten einfacher Typen besonders effizient behandelt werden, verwenden wir hier die kurzen einfachen Typen wenn es um Typen von Wertausdrücken geht und die längeren Strukturtypen, wenn der Aspekt eines Verzeichnisses für Einträge im Vordergrund steht. Dies ist aber nur ein stilistischer Aspekt, es soll damit nicht gesagt werden, daß ein Programm mit »int« schneller läuft als mit »global::System.Int32«. In fast allen Fälle sind die Aliasse in einem Programm so austauschbar, wie oben gezeigt.
Übungsfragen
? Benanntes
Wofür stehen die folgenden Namen jeweils? (Typ, Wert oder Namensraum?)
- »global::System«
- »global::System.Int32«
- »global::System.Int32.MaxValue«
? Enthaltensein
Was kann man aus der Schreibweise »alpha.gamma« in C♯ normalerweise entnehmen?
- »alpha« ist in »gamma« enthalten
- »gamma« ist in »alpha« enthalten
- keiner der obigen Antwortvorschläge trifft zu
? Ausdrücke
Welcher der folgenden Ausdrücke ist ein Wertausdruck?
o »global::System.Int32«
o »global::System.Int32.MaxValue«
? Namen
Welcher der folgenden Namen ist ein Bezeichner, welcher qualifiziert und welcher vollständig qualifiziert?
- »global::System.Int32.MaxValue«
- »MaxValue«
- »Int32.MaxValue«
Zitate *
- C♯LS5
- Members
- Namespaces and types have members. The members of an entity are generally available through the use of a qualified name that starts with a reference to the entity, followed by a “.” token, followed by the name of the member.
- C♯LS5
- A qualified-alias-member is defined as follows:
- qualified-alias-member:
identifier :: identifier type-argument-listopt - A qualified-alias-member can be used as a namespace-or-type-name (§3.8) or as the left operand in a member-access (§7.6.4).