Что означают ref, val и out для параметров метода?

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

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

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

16.08.2008 08:46:16
4 ОТВЕТА
РЕШЕНИЕ

По умолчанию (в 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.

27
23.05.2017 11:54:56
«копия ссылки на этот объект» или «ссылка на копию этого объекта»?
bjan 25.10.2012 07:43:14

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
3
16.08.2008 08:58:50

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

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

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

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

2
23.05.2017 10:31:18

Еще одно замечание относительно 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) {}
8
16.08.2008 13:18:05