Книга: C# 4.0: полное руководство

Возврат объектов из методов

Возврат объектов из методов

Метод может возвратить данные любого типа, в том числе и тип класса. Ниже в качестве примера приведен вариант класса Rect, содержащий метод Enlarge(), в котором строится прямоугольник с теми же сторонами, что и у вызывающего объекта прямоугольника, но пропорционально увеличенными на указанный коэффициент.

// Возвратить объект из метода.
using System;
class Rect {
  int width;
  int height;
  public Rect(int w, int h) {
    width = w;
    height = h;
  }
  public int Area() {
    return width * height;
  }
  public void Show() {
    Console.WriteLine(width + " " + height);
  }
  /* Метод возвращает прямоугольник со сторонами, пропорционально увеличенными на указанный коэффициент по сравнению с вызывающим объектом прямоугольника. */
  public Rect Enlarge(int factor) {
    return new Rect(width * factor, height * factor);
  }
}
class RetObj {
  static void Main() {
    Rect rl = new Rect(4, 5);
    Console.Write("Размеры прямоугольника rl: ");
    rl.Show();
    Console.WriteLine("Площадь прямоугольника rl: " + rl.Area());
    Console.WriteLine();
    // Создать прямоугольник в два раза больший прямоугольника rl.
    Rect r2 = rl.Enlarge(2);
    Console.Write("Размеры прямоугольника r2: "); r2.Show();
    Console.WriteLine("Площадь прямоугольника r2: " + r2.Area());
  }
}

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

Размеры прямоугольника r1: 4 5
Площадь прямоугольника r1: 20
Размеры прямоугольника г2: 8 10
Площадь прямоугольника г2: 80

Когда метод возвращает объект, последний продолжает существовать до тех пор, пока не останется ссылок на него. После этого он подлежит сборке как "мусор". Следовательно, объект не уничтожается только потому, что завершается создавший его метод.

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

// Использовать фабрику класса.
using System;
class MyClass {
  int a, b; // закрытые члены класса
  // Создать фабрику для класса MyClass.
  public MyClass Factory(int i, int j) {
    MyClass t = new MyClass();
    t.a = i;
    t.b = j;
    return t; // возвратить объект
  }
  public void Show() {
    Console.WriteLine("а и b: " + a + " " + b);
  }
}
class MakeObjects {
  static void Main() {
    MyClass ob = new MyClass();
    int i, j;
    // Сформировать объекты, используя фабрику класса.
    for(i=0, j =10; i < 10; i++, j--) {
      MyClass anotherOb = ob.Factory(i, j); // создать объект
      anotherOb.Show();
    }
    Console.WriteLine() ;
  }
}

Вот к какому результату приводит выполнение этого кода.

а и b: 0 10
а и b: 1 9
а и b: 2 8
а и b: 3 7
а и b: 4 6
а и b: 5 5
а и b: 6 4
а и b: 7 3
а и b: 8 2
а и b: 9 1

Рассмотрим данный пример более подробно. В этом примере конструктор для класса МуСlass не определяется, и поэтому доступен только конструктор, вызываемый по умолчанию. Это означает, что значения переменных а и b нельзя задать с помощью конструктора. Но в фабрике класса Factory() можно создать объекты, в которых задаются значения переменных а и b. Более того, переменные а и b являются закрытыми, и поэтому их значения могут быть заданы только с помощью фабрики класса Factory().

В методе Main() получается экземпляр объекта класса МуСlass, а его фабричный метод используется в цикле for для создания десяти других объектов. Ниже приведена строка кода, в которой создаются эти объекты.

MyClass anotherOb = ob.Factory(i, j); // создать объект

На каждом шаге итерации цикла создается переменная ссылки на объект anotherOb, которой присваивается ссылка на объект, формируемый фабрикой класса. По завершении каждого шага итерации цикла переменная anotherOb выходит за пределы области своего действия, а объект, на который она ссылается, утилизируется.

Возврат массива из метода

В C# массивы реализованы в виде объектов, а это означает, что метод может также возвратить массив. (В этом отношении C# отличается от C++, где не допускается возврат массивов из методов.) В качестве примера ниже приведена программа, в которой метод FindFactors() возвращает массив, содержащий множители переданного ему аргумента.

// Возвратить массив из метода,
using System;
class Factor {
  /* Метод возвращает массив facts, содержащий множители аргумента num. При возврате из метода параметр numfactors типа out будет содержать количество обнаруженных множителей. */
  public int[] FindFactors(int num, out int numfactors) {
    int[] facts = new int[80]; // размер массива 80 выбран произвольно
    int i, j;
    // Найти множители и поместить их в массив facts.
    for(i=2, j=0; i < num/2 + 1; i++)
      if( (num%i)==0 ) {
        facts[j] = i;
        j++;
      }
    numfactors = j ; return facts;
  }
}
class FindFactors {
  static void Main() {
    Factor f = new Factor();
    int numfactors;
    int[] factors;
    factors = f.FindFactors(1000, out numfactors);
    Console.WriteLine("Множители числа 1000: ");
    for(int i=0; i < numfactors; i++)
      Console.Write(factors[i] + " ") ;
    Console.WriteLine() ;
  }
}

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

Множители числа 1000:
2 4 5 8 10 20 25 40 50 100 125 200 250 500

В классе Factor метод FindFactors() объявляется следующим образом.

public int[] FindFactors(int num, out int numfactors) {

Обратите внимание на то, как указывается возвращаемый массив типа int. Этот синтаксис можно обобщить. Всякий раз, когда метод возвращает массив, он указывается аналогичным образом, но с учетом его типа и размерности. Например, в следующей строке кода объявляется метод someMeth(), возвращающий двумерный массив типа double.

public double[,] someMeth()    {    //    ...

Оглавление книги


Генерация: 1.124. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз