Was bedeuten ref, val und out für Methodenparameter?
Frage
Ich suche eine klare, prägnante und genaue Antwort.
Idealerweise als eigentliche Antwort, obwohl Links zu guten Erklärungen willkommen sind.
Dies gilt auch für VB.Net, die Schlüsselwörter sind jedoch unterschiedlich - ByRef
Und ByVal
.
Lösung
Standardmäßig (in C#) wird beim Übergeben eines Objekts an eine Funktion tatsächlich eine Kopie des Verweises auf dieses Objekt übergeben.Durch das Ändern des Parameters selbst wird nur der Wert im Parameter geändert, nicht jedoch die angegebene Variable.
void Test1(string param)
{
param = "new value";
}
string s1 = "initial value";
Test1(s1);
// s1 == "initial value"
Benutzen out
oder ref
übergibt einen Verweis auf die im Aufruf der Funktion angegebene Variable.Alle Änderungen am Wert eines out
oder ref
Der Parameter wird an den Aufrufer zurückgegeben.
Beide out
Und ref
verhalten sich bis auf einen kleinen Unterschied identisch: ref
Parameter müssen vor dem Aufruf initialisiert werden, while out
Parameter können nicht initialisiert werden.Durch Erweiterung, ref
Parameter werden garantiert zu Beginn der Methode initialisiert, while out
Parameter werden als nicht initialisiert behandelt.
void Test2(ref string param)
{
param = "new value";
}
void Test3(out string param)
{
// Use of param here will not compile
param = "another value";
}
string s2 = "initial value";
string s3;
Test2(ref s2);
// s2 == "new value"
// Test2(ref s3); // Passing ref s3 will not compile
Test3(out s2);
// s2 == "another value"
Test3(out s3);
// s3 == "another value"
Bearbeiten:Als dp weist darauf hin, dass der Unterschied zwischen out
Und ref
wird nur vom C#-Compiler erzwungen, nicht von der CLR.Soweit ich weiß, gibt es für VB kein Äquivalent out
und implementiert ref
(als ByRef
), passend zur Unterstützung der CLR.
Andere Tipps
Eine zusätzliche Anmerkung zu ref vs.aus:Die Unterscheidung zwischen den beiden wird vom C#-Compiler erzwungen.Die CLR unterscheidet nicht zwischen out und ref.Das bedeutet, dass es keine zwei Methoden geben kann, deren Signaturen sich nur durch ein out oder ref unterscheiden
void foo(int value) {}
// Only one of the following would be allowed
// valid to overload with ref
void foo(ref int value) {}
// OR with out
void foo(out int value) {}
out
bedeutet, dass der Parameter durch die Methode initialisiert wird:
int result; //not initialised
if( int.TryParse( "123", out result ) )
//result is now 123
else
//if TryParse failed result has still be
// initialised to its default value (0)
ref
erzwingt die Übergabe der zugrunde liegenden Referenz:
void ChangeMyClass1( MyClass input ) {
input.MyProperty = "changed by 1";
input = null;
//can't see input anymore ...
// I've only nulled my local scope's reference
}
void ChangeMyClass2( ref MyClass input ) {
input.MyProperty = "changed by 2";
input = null;
//the passed reference is now null too.
}
MyClass tester = new MyClass { MyProperty = "initial value" };
ChangeMyClass1( tester );
// now tester.MyProperty is "changed by 1"
ChangeMyClass2( ref tester );
// now tester is null
Eine meiner eigenen Fragen bei stackoverflow befasst sich ebenfalls mit diesem Thema.
Es geht um „Übergabe als Referenz“ und „Übergabe als Wert“ in verschiedenen Arten von Sprachen, c# ist enthalten Vielleicht finden Sie dort auch einige zusätzliche Informationen.
Im Grunde kommt es darauf an:
- Ref:Der Parameter mit dem Schlüsselwort ref wird übergeben durch Verweis
- aus:Der Parameter mit dem Schlüsselwort out wird als behandelt Ausgabeparameter
Aber das ist wirklich die grundlegendste Antwort, die Sie geben können, da sie etwas komplexer ist, als sie hier angegeben wird