Что используется параметр out в С#

Не могли бы вы рассказать мне, что такое точное использование параметра out?

Связанный с нами вопрос:
В чем разница между ref и out? (С#)

Ответ 1

Лучший пример хорошего использования параметра out - в методах TryParse.

int result =-1;
if (!Int32.TryParse(SomeString, out result){
    // log bad input
}

return result;

Использование TryParse вместо ParseInt устраняет необходимость обработки исключений и делает код более элегантным.

Параметр out по существу допускает более одного возвращаемого значения из метода.

Ответ 2

Ключ параметра метода out метод метода вызывает метод ссылаются на ту же переменную, которая была перешел в метод. Любые изменения сделанный параметру в методе будет отражена в этой переменной когда управление переходит к вызывающий метод.

Объявление метода out полезно, когда вы хотите, чтобы метод возвращал несколько значения. Метод, который использует параметр все равно может вернуть значение. метод может иметь более одного Параметр.

Чтобы использовать параметр out, аргумент должен быть явно передан метод в качестве аргумента. Значение аргумента out не будет передан к параметру out.

Переменная, переданная как аргумент out не нужно инициализировать. Однако out должен быть присвоен значение перед возвратом метода.

Пример:

using System;
public class MyClass 
{
   public static int TestOut(out char i) 
   {
      i = 'b';
      return -1;
   }

   public static void Main() 
   {
      char i;   // variable need not be initialized
      Console.WriteLine(TestOut(out i));
      Console.WriteLine(i);
   }
}

Ответ 3

http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx

Параметры вывода выводятся только параметры, означающие, что они могут только передать значение из функции. Мы создаем параметр "out" , предшествуя типу данных параметров с помощью модификатора out. Когда когда-либо передается параметр "out" , в функцию передается только неназначенная ссылка.

using System;
class ParameterTest
{
 static void Mymethod(out int Param1)
 {
  Param1=100;
 }
 static void Main()
 {
  int Myvalue=5;
  MyMethod(Myvalue);
  Console.WriteLine(out Myvalue);             
 }
}

Вывод вышеуказанной программы будет равен 100, поскольку значение параметра "out" передается обратно вызывающей части. Примечание

Модификатор "out" должен предшествовать параметру, передаваемому даже в вызывающей части. Параметры "out" не могут использоваться в функции перед назначением ему значения. Значение должно быть назначено параметру "out" перед возвратом метода.

Ответ 4

from http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx

Один из способов определения параметров - это то, что они похожи на дополнительные возвращаемые значения метода. Они очень удобны, когда метод возвращает более одного значения, в этом примере firstName и lastName. Однако из-за параметров можно злоупотреблять. В качестве хорошего стиля программирования, если вы обнаружите, что пишете метод с множеством параметров, вам следует подумать о реорганизации вашего кода. Одно из возможных решений - упаковать все возвращаемые значения в одну структуру.

В противоположность, параметры ref считаются первоначально назначенными вызываемым. Таким образом, вызываемому не требуется назначать параметр ref перед использованием. Параметры параметров передаются как в метод, так и вне его.

Ответ 5

Кроме того, вы можете иметь несколько возвращаемых значений, другое использование - уменьшить накладные расходы при копировании большого типа значений в метод. Когда вы передаете что-то методу, копия значения того, что что-то сделано. Если это ссылочный тип (например, строка), то создается копия ссылки (значение ссылочного типа). Однако при копировании типа значения (a struct, например int или double) выполняется копия всего объекта (значение типа значения - это сама вещь). Теперь ссылка составляет 4 байта (в 32-разрядных приложениях), а int - 4 байта, поэтому копирование не является проблемой. Однако возможно иметь очень большие типы значений, и, хотя это не рекомендуется, иногда это может потребоваться. И когда у вас есть тип значения, скажем, 64 байта, стоимость копирования его методам является запретительной (особенно когда вы используете такой большой struct по соображениям производительности в первую очередь). Когда вы используете out, копия объекта не производится, вы просто ссылаетесь на одно и то же.

public struct BigStruct
{
  public int A, B, C, D, E, F, G, H, J, J, K, L, M, N, O, P;
}

SomeMethod(instanceOfBigStruct); // A copy is made of this 64-byte struct.

SomeOtherMethod(out instanceOfBigStruct); // No copy is made

Второе использование непосредственно в соответствии с этим заключается в том, что, поскольку вы не делаете копию структуры, но ссылаетесь на ту же самую вещь в методе, что и вне метода, любые изменения, внесенные в объект внутри метод, сохраняются вне метода. Это уже имеет место в ссылочном типе, но не в типах значений.

Некоторые примеры:

 public void ReferenceExample(SomeReferenceType s)
 {
   s.SomeProperty = "a string"; // The change is persisted to outside of the method
 }

 public void ValueTypeExample(BigStruct b)
 {
   b.A = 5; // Has no effect on the original BigStruct that you passed into the method, because b is a copy!
 }

 public void ValueTypeExampleOut(out BigStruct b)
 {
   b = new BigStruct();
   b.A = 5; // Works, because you refer to the same thing here
 }

Теперь вы заметили, что внутри ValueTypeExampleOut я сделал экземпляр new BigStruct. Это связано с тем, что если вы используете out, перед тем, как выйти из метода, вы должны назначить переменную.

Однако существует еще одно ключевое слово ref, которое идентично, за исключением того, что вы не вынуждены назначать его внутри метода. Тем не менее, это также означает, что вы не можете передать неопределенную переменную, которая сделает этот хороший шаблон Try.. не компилируемым при использовании с ref.

int a;
if(TrySomething(out a)) {}

Это работает, потому что TrySomething вынужден присваивать что-то a.

int a;
if(TrySomething(ref a)) {} 

Это не сработает, потому что a не назначен (только что объявлен) и ref требует, чтобы вы использовали его только с назначенной переменной.

Это работает, потому что a назначается:

int a = 0;
if(TrySomething(ref a)) {}

Однако в обоих случаях (ref и out) любые изменения, сделанные в a внутри метода TrySomething, сохраняются до a.

Как я уже сказал, изменения, сделанные для ссылочного типа, сохраняются вне метода, в котором вы их создаете, потому что через ссылку вы ссылаетесь на одно и то же.

Однако это ничего не делает:

public void Example(SomeReferenceType s)
{
  s = null;
}

Здесь вы просто установите для копии ссылки на s значение null, которое существует только в рамках метода. Он имеет нулевой эффект на все, что вы передали в метод.

Если вы хотите сделать это по любой причине, используйте это:

public void Example1(ref SomeReferenceType s)
{
  s = null; // Sets whatever you passed into the method to null
}

Я думаю, что это охватывает все варианты использования out и ref.

Ответ 6

Типичным примером использования является метод, который должен возвращать несколько вещей, поэтому он не может просто использовать возвращаемое значение. Обычно возвращаемое значение используется для флага успеха, а параметр out устанавливает значения, когда метод успешно.

Классический пример:

public bool TryGet( 
   string key,
   out string value
)

Если он вернет значение true, значение будет установлено. В противном случае это не так. Это позволяет писать код, например:

string value;
if (!lookupDictionary.TryGet("some key", out value))
  value = "default";

Обратите внимание, что это не требует, чтобы вы вызывали Содержит перед использованием индексатора, что делает его более быстрым и чистым. Я также должен добавить, что, в отличие от очень похожего модификатора ref, компилятор не будет жаловаться, если параметр out никогда не был инициализирован.

Ответ 7

Джон Скит описывает различные способы передачи параметров в деталях в этой статье. Короче говоря, параметр out - это параметр, который передается неинициализированному методу. Затем этот метод должен инициализировать параметр перед любым возможным возвратом.

Ответ 8

обычно мы не можем получить переменные внутри функции, если мы не получаем возвращаемое значение. но используйте ключевое слово "out", мы можем изменить его значение с помощью функции.

Ответ 9

Проще говоря, передайте любую переменную в функцию по ссылке, чтобы любые изменения, внесенные в эту переменную на стороне этой функции, были постоянными, когда функция вернется из выполнения.