Материал предоставлен http://it.rfet.ru

Использование модификатора параметра out

Иногда ссылочный параметр требуется использовать для получения значения из метода, а не для передачи ему значения. Допустим, что имеется метод, выполняющий некоторую функцию, например, открытие сетевого сокета и возврат кода успешного или неудачного завершения данной операции в качестве ссылочного параметра. В этом случае методу не передается никакой информации, но в то же время он должен возвратить определенную информацию. Главная трудность при этом состоит в том, что параметр типа ref должен быть инициализирован определенным значением до вызова метода. Следовательно, чтобы воспользоваться параметром типа ref, придется задать для аргумента фиктивное значение и тем самым преодолеть данное ограничение. Правда, в C# имеется более подходящий вариант выхода из подобного затруднения — воспользоваться модификатором параметра out.

Модификатор параметра out подобен модификатору ref, за одним исключением: он служит только для передачи значения за пределы метода. Поэтому переменной, используемой в качестве параметра out, не нужно (да и бесполезно) присваивать какое-то значение. Более того, в методе параметр out считается неинициализированным, т.е. предполагается, что у него отсутствует первоначальное значение. Это означает, что значение должно быть присвоено данному параметру в методе до его завершения. Следовательно, после вызова метода параметр out будет содержать некоторое значение.

Ниже приведен пример применения модификатора параметра out. В этом примере программы для разделения числа с плавающей точкой на целую и дробную части используется метод GetParts() из класса Decompose. Обратите внимание на то, как возвращается каждая часть исходного числа.

// Использовать модификатор параметра out.

using System;

class Decompose {

  /* Разделить числовое значение с плавающей точкой на
    целую и дробную части.  */
  public int GetParts(double n, out double frac) {
    int whole;

    whole = (int)n;
    frac = n - whole;  // передать дробную часть числа через параметр frac
    return whole; // возвратить целую часть числа
  }
}

class UseOut {
  static void Main() {
    Decompose ob = new Decompose();
    int i;
    double f;

    i = ob.GetParts(10.125, out f);

    Console.WriteLine("Целая часть числа равна " + i);
    Console.WriteLine("Дробная часть числа равна " + f);
  }
}

Выполнение этой программы дает следующий результат.

Целая часть числа равна 10
Дробная часть числа равна 0,125

Метод GetParts() возвращает два фрагмента информации. Во-первых, целую часть исходного числового значения переменной n обычным образом с помощью оператора return. И во-вторых, дробную часть этого значения посредством параметра frac типа out. Как показывает данный пример, используя модификатор параметра out, можно организовать возврат двух значений из одного и того же метода.

Разумеется, никаких ограничений на применение параметров out в одном методе не существует. С их помощью из метода можно возвратить сколько угодно фрагментов информации. Рассмотрим пример применения двух параметров out. В этом примере программы метод HasComFactor() выполняет две функции. Во-первых, он определяет общий множитель (кроме 1) для двух целых чисел, возвращая логическое значение true, если у них имеется общий множитель, а иначе — логическое значение false. И во-вторых, он возвращает посредством параметров типа out наименьший и наибольший общий множитель двух чисел, если таковые обнаруживаются.

// Использовать два параметра типа out.

using System;

class Num {
  /* Определить, имеется ли у числовых значений переменных х и v общий множитель. Если имеется, то возвратить наименьший и наибольший множители посредством параметров типа out.  */
  public bool HasComFactor(int x, int y, out int least, out int greatest) {

    int i;
    int max = x < y ? x : y;
    bool first = true;

    least = 1;
    greatest = 1;

    // Найти наименьший и наибольший общий множитель.
    for (i = 2; i <= max / 2 + 1; i++) {
      if (((y % i) == 0) & ((x % i) == 0)) {
        if (first) {
          least = i;
          first = false;
        }
        greatest = i;
      }
    }

    if (least != 1)
      return true;
    else
      return false;
  }
}

class DemoOut {
  static void Main() {
    Num ob = new Num();
    int lcf, gcf;

    if (ob.HasComFactor(231, 105, out lcf, out gcf)) {
      Console.WriteLine("Наименьший общий множитель " +
                        "чисел 231 и 105 равен " + lcf);
      Console.WriteLine("Наибольший общий множитель " +
                        "чисел 231 и 105 равен " + gcf);
    } else
      Console.WriteLine("Общий множитель у чисел 231 и 105 отсутствует.");

    if (ob.HasComFactor(35, 51, out lcf, out gcf)) {
      Console.WriteLine("Наименьший общий множитель " +
                        "чисел 35 и 51 равен " + lcf);
      Console.WriteLine("Наибольший общий множитель " +
                        "чисел 35 и 51 равен " + gcf);
    } else
      Console.WriteLine("Общий множитель у чисел 35 и 51 отсутствует.");
  }
}

Обратите внимание на то, что значения присваиваются переменным lcf и gcf в методе Main() до вызова метода HasComFactor(). Если бы параметры метода HasComFactor() были типа ref, а не out, это привело бы к ошибке. Данный метод возвращает логическое значение true или false, в зависимости от того, имеется ли общий множитель у двух целых чисел. Если он имеется, то посредством параметров типа out возвращаются наименьший и наибольший общий множитель этих чисел.

Ниже приведен результат выполнения данной программы.

Наименьший общий множитель чисел 231 и 105 равен 3
Наибольший общий множитель чисел 231 и 105 равен 21
Общий множитель у чисел 35 и 51 отсутствует.
Использование модификатора параметра refИспользование модификаторов ref и out для ссылок на объекты