Überladung und Signaturen der Dokumentation in C# (Überladung und Signaturen der Dokumentation in C#), Lektion, Seite 723493
https://www.purl.org/stefan_ram/pub/ueberladung_csharp (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C#-Kurs

Überladung und Signaturen in C♯ 

Einen einfachen Namen einer Methode (also einen Bezeichner) bezeichnen wir auch als ein Verb  (vom lateinischen „verbum“ – „Wort“).

Ein Verb kann zu verschiedenen  Methoden derselben Klasse  gehören, welche sich durch die Anzahl  und/oder den Typ  ihrer Parameter unterscheiden.

Die Methode »global::System.Math.Abs« ergibt den Betrag  ihres Argumentes (also den Abstand des Arguments zur Zahl 0).

In der Klasse »global::System.Math« gibt es zwei  Methoden mit dem Verb »Abs«, aber nur eine mit dem Verb »Floor«.

Dokumentationen zum Verb »Abs« der Klasse »global::System.Math« (verändert und übersetzt)
Namensraum »global::System«
Klasse »Math«
public static double Abs( double d )
Ergibt den Betrag des Argumentwerts.
public static int Abs( int d )
Ergibt den Betrag des Argumentwerts.

Man sagt, daß ein Verb, das mehr als nur einen Eintrag in der Dokumentation eines Typs hat, überladen  (d.h. mehrfach mit einer Bedeutungen „beladen“) sei. Und man spricht auch von einer „überladenen Methode “, um zu sagen, daß es noch andere Methoden mit demselben Verb im selben Referenztyp gibt.

Methodensignatur

Um eine Methode eindeutig  bezeichnen zu können (wenn ihre Klasse schon festgelegt ist), ist es angesichts der Möglichkeit der Überladung notwendig, zusätzlich zum Verb auch noch die Parametertypen  mit anzugeben. Die Kombination aus Verb und den Parametertypen nennt man Methodensignatur  oder kurz Signatur. Die obige Dokumentation behandelt also unter anderem die Signatur »Abs(double)« und die Signatur »Abs(int)«.

Mögliche Aussprachen von »Abs(double)«
„Abs von double“
„Abs double“ (kurz)

Angabe einer Methode

Da erst die Signatur  eine Methode innerhalb einer Klasse genau bestimmt und nicht schon das Verb  der Methode, gibt man Methoden mit ihrer Signatur  an.

Man spricht also beispielsweise von „der Methode mit der Signatur »Abs(double)«“ oder einfach von „der Methode »Abs(double)«“ und nicht einfach von der Methode »Abs«.

Wir unterscheiden daher zwischen der Methode »Abs(double)« und der Methode »Abs(int)« (das sind zwei verschiedene  Methoden (Signaturen), die aber dasselbe  Verb miteinander teilen).

Man kann jedoch von „der  Methode »Abs«“ sprechen, wenn es nicht darauf ankommt, welche Überladung genau gemeint ist, oder man sich auf alle Überladungen gemeinsam beziehen will, obwohl der Singular nicht ganz korrekt ist, da es ja mehrere  Methoden mit dem Verb »Abs« gibt.

Angabe einer Methode ohne Parameter

Man spricht von der Methode »random()« mit leeren  Klammern, also der Information, daß sie keine  Parameter hat, statt nur von der Methode »random«. Allerdings darf man »random()« in solchen Fällen nicht  mit dem Aufruf  der Methode verwechseln – bei Methoden ohne Parameter sieht die Angabe der Methodensignatur nämlich wie ein Aufruf der Methode aus. Man muß manchmal aus dem Zusammenhang entnehmen, ob mit solch einer Angabe mit leeren Klammern eine Methodensignatur oder ein Aufruf gemeint ist.

Qualifizierte Signaturen

Um eine Methode eindeutig zu bezeichnen, wenn nicht schon aus dem Zusammenhang klar ist, zu welcher Klasse sie gehört, ist es nötig, zusätzlich zur Methodensignatur auch noch die Klasse anzugeben, wie beispielsweise in »global::System.Math.Abs(int)«, der Methodensignatur »Abs(int)« in der Klasse »global::System.Math«. Wir bezeichnen eine um den Klassennamen erweiterte Methodensignatur hier manchmal als qualifizierte Methodensignatur.

Aufrufsignatur

Neben der Signatur einer Methode aus der Dokumentation gibt es auch noch die Signatur eines Aufrufs aus dem Quelltext, die Aufrufsignatur.

Die Aufrufsignatur eines Aufrufs erhält man, indem man alle Argumente durch ihren Typ ersetzt.

So hat der Aufruf »Abs( 2 )« die Aufrufsignatur »Abs(int)«, und der Aufruf »Abs( 2.0 )« hat die Aufrufsignatur »abs(double)«.

Auflösung von Ausdrücken

In dem folgenden Programm wird »global::System.Math.Abs« mit einem Argument vom Typ »double« aufgerufen. Ersetzen wir im Aufruf den Argumentausdruck »-2.0« durch seinen Typ »double«, so erhalten wir die Aufrufsignatur  »Abs(double)«. Diese paßt nur zur Methodensignatur »Abs(double)« aus der Dokumentation (in dem Sinne, daß der Aufruf »java.lang.Math.Abs( -2.0 )« korrekt wäre, wenn es in der Klasse nur  diese Methode »Abs(double)« geben würde). Daher wird die Methode aufgerufen, welche die Methodensignatur »Abs(double)« hat.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Math.Abs( -2.0 )/4 ); }}
Protokoll
0.5

An der Ausgabe »0.5« erkennen wir, daß der Dividend »global::System.Math.Abs( -2.0 )« den Typ »double« haben muß.

In dem folgenden Programm wird »global::System.Math.Abs« mit einem Argument vom Typ »int« aufgerufen. Ersetzen wir im Aufruf den Argumentausdruck »-2« durch seinen Typ »int«, so erhalten wir die Aufrufsignatur »Abs(int)«. Diese paßt sowohl zur Methodensignatur »Abs(int)« als auch zur Methodensignatur »Abs(double)« aus der Dokumentation, da der Argumenttyp »int« sowohl implizit in den Parametertyps »int« als auch in den Parametertyps »double« gewandelt werden kann (in dem Sinne, daß der Aufruf »global::System.Math.Abs( -2 )« sowohl korrekt wäre, wenn es in der Klasse die Methode »Abs(int)« geben würde, als auch, wenn es in der Klasse nur die Methode »Abs(double)« geben würde.). In solche Fällen wird unter den passenden Signaturen die am besten passende  Methodensignatur ausgewählt. Dies ist im folgenden Programm die Methodensignatur »Abs(int)«, da sie genau  zur Aufrufsignatur »Abs(int)« paßt.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Math.Abs( -2 )/4 ); }}
Protokoll
0

An der Ausgabe »0« erkennen wir, daß der Dividend »global::System.Math.Abs( -2 )« den Typ »int« haben muß.

Im allgemeinen wird die Methode aufgerufen, deren Signatur am besten  zur Signatur des Aufrufs paßt.

Die komplizierten Details des Auswahlverfahrens in Fällen, in denen die am besten passende Signatur nicht so eindeutig erkannt werden kann wie in den obigen Beispielen, sind in C# Language Specification, Version 6, 7.5.3 Overload resolution  beschrieben.

Es gilt als Fehler, wenn es mehrere Methodensignaturen gibt, die gleich gut  zu einer Aufrufsignatur passen.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Math.Floor( 2 )); }}
Protokoll
Program.cs(4,27): error CS0121: The call is ambiguous between the following methods or properties: 'Math.Floor(decimal)' and 'Math.Floor(double)'

Gründe für eine Überladung

Der Typ des Aufrufs verschiedener Methoden mit demselben Verb muß nicht gleich sein, sondern kann für jede Signatur willkürlich festgelegt werden. Im Falle des qualifizierten Verbs »java.lang.Math.abs« hat der Aufruf der Methode mit einem double-Parameter den Typ »double«, während der Aufruf der Methode mit einem int-Parameter den Typ »int« hat. Dies bedeutet, daß in diesem Falle der Typ des Arguments auch der Typ des Aufrufs ist. Durch die Überladung bleibt in diesem Fall also der Typ des Arguments „erhalten“, was manchmal erwünscht ist.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Math.Abs( 2.0 )/4 ); }}
Protokoll
0.5
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Math.Abs( 2 )/4 ); }}
Protokoll
0

Bei der Methode »global::System.Math.Sqrt« (Quadratwurzel) geht der Typ des Arguments hingegen verloren. Der Aufruf hat immer den Typ »double«.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Math.Sqrt( 4.0 )/4 ); }}
Protokoll
0.5
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Math.Sqrt( 4 )/4 ); }}
Protokoll
0.5
Tabelle

Aufrufsignatur aufgerufene Methode Aufruftyp

Abs(double) Abs(double) double
Abs(int) Abs(int) int

Sqrt(double) sqrt(double) double
Sqrt(int) sqrt(double) double

Eine Überladung eines Verbs mit einer int- und einer double-Signatur wird vorgenommen, wenn das Verb int-Werte anders  als double-Werte behandeln soll. Würde es nur eine einzige double-Methode geben, so würde diese Methode es nämlich gar nicht feststellen können, wenn sie mit einem int-Werte aufgerufen wird, da dieser beim Aufruf immer automatisch in einen double-Wert umgewandelt werden würde bevor er der Methode bekannt gegeben wird.

Polymorphie

Polymorphie  bedeutet allgemein für Aufrufe, daß die Auswahl der aufgerufenen Methode nicht nur vom im Aufruf angegebenen Namen der Methode  abhängt, sondern auch von den Typen der Argumente  abhängen kann.

Die oben beschriebene Überladung  ist eine Form von Polymorphie, da aus der Kombination  eines Methodennamens und des Typs  der Argumente die zu verwendende Methode bestimmt wird.

Beispielsweise enthält der Aufruf »global::System.Math.Abs« den Methodennamen »global::System.Math.Abs« und den Argumentausdruck »2.0«. Durch die Kombination des Methodennamens mit dem Typ des Arguments, also durch die Aufrufsignatur »global::System.Math.Abs(double)« wird dann festgelegt, daß die Implementation (Methode) »global::System.Math.Abs(double)« aufgerufen wird.

Beispiele zu Typwandlungen

Einige Typwandlungen lassen sich als Methodenaufrufe mit einem Argument schreiben.

Obwohl es viele verschiedene Möglichkeiten solcher Aufrufe gibt, reicht es, sich für sie den Begriff »To« zu merken.

Ein Begriff für Wandlungen
To

Durch Anfügen eines der vier Typnamen  »Decimal«, »Double«, »Decimal«, »Decimal« ergeben sich so vier Verben (also Bezeichner für Methoden), die jeweils ausdrücken in welchen Typ  gewandelt werden soll.

Vier Verben für Wandlungen

ToDecimal

ToDouble

ToInt32

ToString

Vier Methoden mit diesen Verben finden sich in der Klasse »global::System.Convert«.

Die Namen der verwendeten Wandlungsmethoden

global::System.Convert.ToDecimal

global::System.Convert.ToDouble

global::System.Convert.ToInt32

global::System.Convert.ToString

Zu jedem einzelnen jener Umwandlungsverben gehören dann diverse Überladung mit Umwandlungsmethoden für verschiedene Argumenttypen.

Beispielsweise ist der Typ eines Aufrufs  des Verbes »ToDecimal« stets »decimal«. Mögliche Argumenttypen  umfassen aber »int«, »double«, »decimal« und »string«.

Der Aufruf »global::System.Convert.ToDecimal(4)« hat beispielsweise den Typ »decimal« und ruft die Überladung (Methode) »global::System.Convert.ToDecimal(int)« auf, das Ergebnis ist die Umwandlung des Wertes »4« in den Datentyp »decimal«, also in den Wert dieses Typs, der den Zahlenwert »4« repräsentiert, das heißt in die Zahl Vier vom Typ »decimal«.

Siehe auch
https://msdn.microsoft.com/en-us/library/system.convert_methods.aspx

Wandlung von »double«

Wandlung von »double« nach »int«

Das folgende Programm enthält eine Wandlung eines double-Wertes in einen int-Wert.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::System.Convert.ToInt32( 5.3 )); }}
global::System.Console.Out
5

Wandlung von »double« nach »decimal«

Das folgende Programm enthält eine Wandlung eines double-Wertes in einen decimal-Wert.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1/global::System.Convert.ToDecimal( 3.0 )); }}
global::System.Console.Out
0.3333333333333333333333333333

Wandlung von »double« in eine Zeichenfolge

Das folgende Programm enthält eine Wandlung eines double-Wertes in eine Zeichenfolge.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + global::System.Convert.ToString( 3.0 )); }}
global::System.Console.Out
13

Wandlung von »int«

Wandlung von »int« nach »double«

Das folgende Programm enthält eine Wandlung eines int-Wertes in einen double-Wert.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1/global::System.Convert.ToDouble( 3 )); }}
global::System.Console.Out
0.333333333333333

Wandlung von »int« nach »decimal«

Das folgende Programm enthält eine Wandlung eines int-Wertes in einen decimal-Wert.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1/global::System.Convert.ToDecimal( 3 )); }}
global::System.Console.Out
0.3333333333333333333333333333

Wandlung von »int« in eine Zeichenfolge

Das folgende Programm enthält eine Wandlung eines int-Wertes in eine Zeichenfolge.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + global::System.Convert.ToString( 3 )); }}
global::System.Console.Out
13

Wandlung von »decimal«

Wandlung von »decimal« nach »int«

Das folgende Programm enthält eine Wandlung eines decimal-Wertes in einen int-Wert.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1/global::System.Convert.ToInt32( 3m )); }}
global::System.Console.Out
0.333333333333333

Wandlung von »decimal« nach »double«

Das folgende Programm enthält eine Wandlung eines decimal-Wertes in einen double-Wert.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1/global::System.Convert.ToDouble( 3m )); }}
global::System.Console.Out
0.333333333333333

Wandlung von »decimal« in eine Zeichenfolge

Das folgende Programm enthält eine Wandlung eines decimal-Wertes in eine Zeichenfolge.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + global::System.Convert.ToString( 3m )); }}
global::System.Console.Out
13

Wandlung von Zeichenfolgen

Wandlung einer Zeichenfolge nach »int«

Das folgende Programm enthält eine Wandlung einer Zeichenfolge in einen int-Wert.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + global::System.Convert.ToInt32( "2" + "3" )); }}
global::System.Console.Out
24

Wandlung einer Zeichenfolge nach »double«

Das folgende Programm enthält eine Wandlung einer Zeichenfolge in einen double-Wert.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1/global::System.Convert.ToDouble( "1" + "0" )); }}
global::System.Console.Out
0.1

Wandlung einer Zeichenfolge nach »decimal«

Das folgende Programm enthält eine Wandlung einer Zeichenfolge in einen decimal-Wert.

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1/global::System.Convert.ToDecimal( "3" )); }}
global::System.Console.Out
0.3333333333333333333333333333

Übungsfragen

?   Überladungen

Wie viele Überladungen hat das Verb »Parse« im Typ »int« (Struktur »global::System.Int32«)?

?   Aufrufsignaturen _

Welche Aufrufsignatur hat der Aufruf »sin( 2.0 )«?

Welche Aufrufsignatur hat der Aufruf »sin( 2 )«?

?   Methoden und Signaturen _

Welche Methodensignatur hat die Methode »Log« der Klasse »global::System.Math«?

?   Aufrufe und Signaturen ⃗

Was trifft für »Abs( 2 )« zu?

?   Aufrufe und Signaturen (1) ⃗

Was trifft für »Abs(int)« zu?

?   Aufrufe und Signaturen (2) ⃗

Was trifft für »random()« zu?

?   Aufrufe und Signaturen (3) ⃗

/    Welche der folgenden einfachen Aufrufe haben die gleiche Signatur?

?   Datentypen ⃗

Welchen Datentyp haben die folgenden Aufrufe jeweils?

Diskussion der Typwandung mit Hilfe von »+« ⃗

Gelegentlich wird die Wandlung in eine Zeichenfolge mit »+ ""« als „unverständlich“ kritisiert. Es wird behauptet, daß ein Leser eines Programms an »+ ""« die Absicht des Programmierers, etwas in eine Zeichenfolge zu wandeln, nicht  erkennen könne. Diese Kritik ist allerdings nicht  berechtigt. Falls ein C♯ -Programmierer die Bedeutung von »+ ""« nicht  kennt, dann liegt dies daran, daß er seine Ausbildung noch nicht beendet hat – aber man kann schlecht verlangen, Programme für Leser schreiben, welche die Programmiersprache nicht kennen. Falls ein C♯ -Programmierer die Bedeutung von »+ ""« aber kennt, dann ist es ihm auch klar, daß damit eine Umwandlung in eine Zeichenfolge beabsichtigt ist, denn warum sollte jemand »+ ""« sonst verwenden?

Die Kritiker würden die Verwendung von »global::System.Convert.ToString« bevorzugen, vermutlich weil dort Englische Wörter vorkommen, die – mehr oder weniger – „erklären“, was gemeint ist, während »+ ""« keine solchen Wörter enthält.

?   Ausgabe vorhersagen ⃗

Das folgende Programm gibt sieben Zeichen aus. Sagen Sie alle sieben Zeichen einzeln voraus!

Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 2E3 + ", " + global::System.Math.Pow( 2, 3 ) ); }}
Protokoll
2000, 8

Übungsaufgaben ⃗

/   Übungsaufgabe ⃗

Schreiben Sie ein Programm, in dem zunächst die Methode »Max(double,double)« aus der Klasse »global::System.Math« und dann die Methode »Max(int,int)« aus derselben Klasse aufgerufen wird.

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723493 stefan_ram:723493 Überladung und Signaturen der Dokumentation in C# Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723493, slrprddef723493, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/ueberladung_csharp