Advanced  Services in, out, und ref Parameter Back Next Up Home


Grundlegendes

Im vorigen Kapitel haben wir den grundsätzlichen Unterschied zwischen call by value und call by reference kennengelernt. Eigentlich werden bei einem Funktionsaufruf immer "nur" Kopien der Variablen übergeben. Es macht aber einen qualitativen Unterschied ob man die Kopie eines Wertes übergibt oder die Kopie eines Zeigers oder vielleicht sogar die Kopie eines Zeigers auf einen Zeiger. Es ist also immer ein Unterschied, ob man einen Werttyp oder einen Referenztyp übergibt. C# unterscheidet zudem dreierlei Arten von Übergabeparametern, in-Parameter, out-Parameter und ref-Parameter.



in-Parameter

"in" ist zwar ein Schlüsselwort, wird aber im Zusammenhang mit Methoden nicht verwendet, im Gegensatz zu out und ref. Parameter, die nur mit Typ und Variablenname deklariert werden nennt man in-Parameter um den Gegensatz zu out- und ref-Parametern hervorzuheben. So werden beispielsweise in den folgenden beiden Methodensignaturen ausschließlich in-Parameter verwenden. Die zweite Signatur beinhaltet aber nur Referenztypen.

In den folgenden drei Beispielen wollen wir das Verhalten von in-Parametern klären.

ValueTypes als in-Parameter

Beispiel 1

Wir rufen in Main die folgenden Methode auf.

public static void Method1(int x)
{
   x = 1;
   Console.WriteLine("x = " + x);
}
public static void Main()
{
   int x = 0;
   Console.WriteLine("x = " + x);
   Method1(x);
   Console.WriteLine("x = " + x);
}

Da die Variable x in der Methode eine Kopie der Variablen x in Main ist, ist folgende Ausgabe nicht verwunderlich.

in-Parameter1

Referenzen als in-Parameter

Beispiel 2

Interessanter wird das nächste Beispiel

public static void Method2(string st)
{
   Console.WriteLine("method2: " + st);
   st = "hallo";
   Console.WriteLine("method2: " + st);
}
public static void Main()
{
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("in-Parameter");
   Console.WriteLine("-----------------------------------");
   string st = "helau";
   Console.WriteLine("st = " + st);
   Method2(st);
   Console.WriteLine("st = " + st);
}

in-Parameter2

string ist ein echter Referenztyp. Trotzdem haben wir die gleiche Situation wie im vorigen Beispiel. Die Erklärung für das unterschiedliche Verhalten folgt am Schluß der Beispiele.

Beispiel 3

In diesem Beispiel verwenden wir eine nichtgenerische ArrayList.

using System.Collections;

public static void Method3(ArrayList al)
{
   al.Add("Method3");
}

Wir übergeben die Liste leer an die Methode.

public static void Main()
{
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("in-Parameter");
   Console.WriteLine("-----------------------------------");
   ArrayList al = new ArrayList();
   Console.WriteLine("size of arraylist = " + al.Count);
   Method3(al);
   Console.WriteLine("size of arraylist = " + al.Count);
}

in-Parameter3

... und erhalten Sie nichtleer zurück.

Beispiel 4

Auch in diesem Beispiel verwenden wir eine ArrayList.

using System.Collections;

public static void Method4(ArrayList al)
{
   al = new ArrayList();
   al.Add("Method4");
}

Wir übergeben die Liste leer an die Methode.

public static void Main()
{
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("in-Parameter");
   Console.WriteLine("-----------------------------------");
   ArrayList al = new ArrayList();
   Console.WriteLine("size of arraylist = " + al.Count);
   Method4(al);
   Console.WriteLine("size of arraylist = " + al.Count);
}

in-Parameter4

... und erhalten Sie leer zurück.

Erklärung:

In Method4 wird der Referenz ein neuer lokaler Wert zugewiesen (roter Code). Die übergebene Referenz wird also nicht verwendet.


out-Parameter

Das Schlüsselwort out muß sowohl in der Signatur der Methode als auch beim Aufruf angegeben werden. Das hat den Vorteil, daß auch beim Aufruf ersichtlich ist um welche Art der Parameterübergabe es sich handelt. Ein out-Parameter wird in der Methode vom Compiler grundsätzlich als eine (noch) nicht initialisierte Variable aufgefaßt, egal ob ihr im aufrufenden Programmm bereits ein Wert zugewiesen wurde oder nicht. Wie bei einem Returnwert erzwingt der Compiler hier eine Wertzuweisung und dieser Wert wird an die aufrufende Methode übermittelt.

ValueTypes als out-Parameter

Beispiel 1

Wir beginnen wieder mit einem ValueType.

public static void Method1(out int x)
{
   // int tmp = x; kann nicht zugewiesen werden
   // ++x ist keine Initialisierung
   x = 17;  // x muß initialisiert werden !
}
static void Main()
{
   // out parameter
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("out-Parameter");
   Console.WriteLine("-----------------------------------");
   int x = 0;
   Method1(out x);  // out muß angegeben werden !!!
   Console.WriteLine("x = " + x);
}

out-Parameter1

Referenzen als out-Parameter

Beispiel 2

public static void Method2(out string st)
{
   st = "hi";  // st muß initialisiert werden !!!
}
static void Main()
{
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("out-Parameter");
   Console.WriteLine("-----------------------------------");
   string str; // str ist nicht initialisiert !
   Method2(out str);  // out muß angegeben werden !
   Console.WriteLine("str = " + str);
}

out-Parameter2

Beispiel 3
using System.Collections;

public static void Method3(out ArrayList al)
{
   al = new ArrayList();
   al.Add("Method3");
}
static void Main()
{
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("out-Parameter");
   Console.WriteLine("-----------------------------------");
   ArrayList ali;  // ali ist nicht initialisiert !
   Method3(out ali);  // out muß angegeben werden !
   Console.WriteLine("ali.Count = " + ali.Count);
}

out-Parameter3


ref-Parameter

Das Schlüsselwort ref muß sowohl in der Signatur der Methode als auch beim Aufruf angegeben werden. Das hat den Vorteil, daß auch beim Aufruf ersichtlich ist um welche Art der Parameterübergabe es sich handelt. Bei einem ref-Parameter wird eine Kopie der Adresse angelegt und übergeben. Daher können ref-Parameter also veränderte Werte an das aufrufende Programm zurückgeben.

ValueTypes als ref-Parameter

Beispiel 1
public static void Method1(ref int x)
{
   x++;
}
static void Main()
{
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("ref-Parameter");
   Console.WriteLine("-----------------------------------");
   int x = 0;
   Console.WriteLine("x = " + x);
   Method1(ref x);  // ref muß angegeben werden !!!
   Console.WriteLine("x = " + x);
}

ref-Parameter1

Referenzen als ref-Parameter

Beispiel 2

public static void Method2(ref string st)
{
   st += "what!";
}
static void Main()
{
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("ref-Parameter");
   Console.WriteLine("-----------------------------------");
   string str = "so ";
   Method2(ref str);  // ref muß angegeben werden !!!
   Console.WriteLine("str = " + str);
}

ref-Parameter2

Beispiel 3

using System.Collections.Generic;

public static void Method3(ref List<String> list)
{
   list.Add("Method3");
}
static void Main()
{
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("ref-Parameter");
   Console.WriteLine("-----------------------------------");
   List strList = new List();
   Console.WriteLine("strList.Count = " + strList.Count);
   Method3(ref strList);  // ref muß angegeben werden !
   Console.WriteLine("strList.Count = " + strList.Count);
}

ref-param3.jpg

Beispiel 4

using System.Collections.Generic;

public static void Method4(ref List<String> list)
{
   list = new List<String>();
}
static void Main()
{
   Console.WriteLine("-----------------------------------");
   Console.WriteLine("ref-Parameter");
   Console.WriteLine("-----------------------------------");
   List stList = new List<String>();
   stList.Add("schau mer mal");
   Console.WriteLine("stList.Count = " + stList.Count);
   Method4(ref stList);  // ref muß angegeben werden !!!
}

ref-Parameter4

Valid XHTML 1.0 Strict top Back Next Up Home