Что означают ref, val и out для параметров метода? - PullRequest
22 голосов
/ 16 августа 2008

Я ищу ясный, краткий и точный ответ.

В идеале, как фактический ответ, хотя ссылки на хорошие объяснения приветствуются.

Это также относится к VB.Net, но ключевые слова различаются - ByRef и ByVal.

Ответы [ 4 ]

27 голосов
/ 16 августа 2008

По умолчанию (в C #) передача объекта в функцию фактически передает копию ссылки на этот объект. При изменении самого параметра изменяется только значение в параметре, а не указанная переменная.

void Test1(string param)
{
    param = "new value";
}

string s1 = "initial value";
Test1(s1);
// s1 == "initial value"

Использование out или ref передает ссылку на переменную, указанную в вызове функции. Любые изменения в значении параметра out или ref будут переданы вызывающей стороне.

И out, и ref ведут себя одинаково, за исключением одного небольшого различия: параметры ref необходимо инициализировать перед вызовом, а параметры out можно неинициализировать. При этом параметры ref гарантированно инициализируются в начале метода, а параметры out обрабатываются как неинициализированные.

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"

Редактировать : Как указывает dp , разница между out и ref обеспечивается только компилятором C #, а не CLR. Насколько я знаю, VB не имеет эквивалента для out и реализует только ref (как ByRef), что соответствует поддержке CLR.

8 голосов
/ 16 августа 2008

Еще одно замечание относительно ref и out: различие между ними обеспечивается компилятором C #. CLR не делает различий между out и ref. Это означает, что у вас не может быть двух методов, подписи которых отличаются только на out или ref

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) {}
3 голосов
/ 16 августа 2008

out означает, что параметр будет инициализирован методом:

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 принудительно передаст базовую ссылку:

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
2 голосов
/ 16 августа 2008

Один из моих собственных вопросов в stackoverflow также обрабатывает эту тему.
Он обрабатывает около «передача по ссылке» и «передача по значению» на разных типах языков, c # включен , так что, возможно, вы также можете найти там дополнительную информацию.

В основном это сводится к:

  • ref: параметр с ключевым словом ref будет передан по ссылке
  • out: параметр с ключевым словом out будет обрабатываться как выходной параметр

но это действительно самый простой ответ, который вы можете дать, поскольку он немного сложнее, чем указано здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...