C#. Передача у функцію одновимірних та багатовимірних масивів екземплярів класу як ref та out параметрів




Передача у функцію одновимірних та багатовимірних масивів екземплярів класу як ref та out параметрів


Зміст


Пошук на інших ресурсах:

1. Особливості передачі посилань на масиви екземплярів класу з використанням модифікаторів ref та out

Існує 2 способи передачі у функцію посилань на масиви екземплярів класу:

  • передача за значенням. У цьому випадку, масив повністю копіюється у функцію. Зміна значень масиву всередині функції не змінить ці значення у викликаючому коді;
  • передача за посиланням. У цьому випадку використовуються модифікатори ref або out. При такій передачі можна змінити кількість елементів у масиві, перерозподілити пам’ять для кожного елементу, заповнити новими значеннями ці елементи масиву.

Отже, при передачі масиву з модифікаторами ref або out:

  • можна змінювати значення самого посилання. Це означає, що можна перерозподілити пам’ять для масиву та його елементів і заповнити новими значеннями елементи масиву;
  • зміна значень елементів масиву всередині функції буде відображатись у викликаючому коді.

 

2. Передача одновимірного масиву типу int як ref параметру. Приклад

У нижченаведеному прикладі розроблено клас Integer, що містить один внутрішній параметр value.

В тестуючому класі Program оголошуються наступні елементи:

  • статична функція GetArray(), яка формує масив випадкових чисел типу Integer. Функція отримує вхідним параметром масив A типу Integer[] як ref-параметр і перевизначає пам’ять для самого посилання A. Функція ще раз виділяє пам’ять для кожного екземпляру і заповнює поля екземпляру значеннями. Зміна значень фіксується у викликаючій функції main();
  • статична функція SumIntegers() – призначена для обчислення суми цілочисельних значень value масиву типу Integer. Функція отримує вхідним параметром масив типу Integer[] як ref-посилання.


Після завершення роботи програми не потрібно звільняти пам’ять. Цим всім займається так званий “прибирач сміття”.

using System;

namespace ConsoleApp2
{
  // Клас Integer - посилальний тип
  class Integer
  {
    public int value; // цілочисельне значення
  }

  class Program
  {
    // Статична функція GetArray() генерує (формує) масив випадкових чисел,
    // масив передається як ref-параметр, можна змінювати саме посилання A
    static void GetArray(ref Integer[] A)
    {
      // 1. Ініціалізувати генератор випадкових чисел
      Random rnd_num = new Random();

      // 2. Змінити кількість елементів у масиві A - перерозподілити пам'ять
      A = new Integer[6]; // змінюється саме посилання - виділити пам'ять для 6 екземплярів

      // 3. Виділити пам'ять для кожного екземпляру окремо
      for (int i = 0; i < A.Length; i++)
      {
        A[i] = new Integer();
      }

      // 4. Заповнити масив випадковими цілими числами в межах [0; 10]
      for (int i = 0; i < A.Length; i++)
      {
        // Усі зміни в масиві будуть відображатись за межами даної функції
        A[i].value = rnd_num.Next(0, 10);
      }

      // 5. Повернення з функції
      return;
    }

    // Статична функція, яка знаходить суму елементів масиву,
    // масив передається за посиланням (з модифікатором ref)
    static int SumIntegers(ref Integer[] A)
    {
      int sum = 0;
      for (int i=0; i<A.Length; i++)
      {
        sum += A[i].value;
      }
      return sum;
    }

    static void Main(string[] args)
    {
      // Передача ref-масиву екземплярів класу в метод

      // 1. Оголосити масив типу Integer
      const int MAX_ITEMS = 8; // максимально-допустима к-сть елементів у масиві
      Integer[] Array;

      // 2. Виділити пам'ять для MAX_ITEMS елементів, сформованих випадково
      Array = new Integer[MAX_ITEMS];

      // 3. Виділити пам'ять для кожного елементу типу Integer
      for (int i = 0; i < Array.Length; i++)
        Array[i] = new Integer();

      // 4. Заповнити масив Array фіксованими значеннями від 1 до Array.Length
      for (int i=0; i<Array.Length; i++)
      {
        Array[i].value = i + 1;
      }

      // 5. Вивести масив на екран в рядок
      Console.WriteLine("Items in Array:");
      for (int i=0; i<Array.Length; i++)
      {
        Console.Write($"{Array[i].value}\t");
      }

      // 6. Заповнити масив Array випадковими числами
      // з допомогою виклику функції GetArray()
      GetArray(ref Array); // функція статична, змінює масив всередині

      // 7. Вивести змінений масив на екран
      Console.WriteLine("\nArray after random forming:");
      for (int i=0; i<Array.Length; i++)
      {
        Console.Write($"{Array[i].value}\t");
      }

      // 8. Обчислити суму елементів зміненого масиву та вивести її на екран
      int summ = Program.SumIntegers(ref Array);
      Console.WriteLine($"\nsumm = {summ}");
    }
  }
}

Результат виконання програми:

Items in Array:
1 2 3 4 5 6 7 8
Array after random forming:
4 3 8 9 7 7
summ = 38

 

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

Даний приклад дуже подібний до прикладу у п. 2 (передача масиву як ref-параметру). Відмінність тільки у функції GetArray(), в якій модифікатор ref замінено на модифікатор out.

using System;

namespace ConsoleApp2
{
  // Клас Integer - посилальний тип
  class Integer
  {
    public int value; // цілочисельне значення
  }

  class Program
  {
    // Статична функція GetArray() генерує (формує) масив випадкових чисел,
    // масив передається як out-параметр, можна змінювати саме посилання A
    static void GetArrayOut(out Integer[] A)
    {
      // 1. Ініціалізувати генератор випадкових чисел
      Random rnd_num = new Random();

      // 2. Змінити кількість елементів у масиві A
      A = new Integer[6]; // змінюється саме посилання - виділити пам'ять для 6 екземплярів

      // 3. Виділити пам'ять для кожного екземпляру окремо
      for (int i = 0; i < A.Length; i++)
      {
        A[i] = new Integer();
      }

      // 4. Заповнити масив випадковими цілими числами в межах [0; 10]
      for (int i = 0; i < A.Length; i++)
      {
        // Усі зміни в масиві будуть відображатись за межами даної функції
        A[i].value = rnd_num.Next(0, 10);
      }

      // 5. Повернення з функції
      return;
    }

    // Статична функція, яка знаходить суму елементів масиву,
    // масив передається за посиланням (з модифікатором ref)
    static int SumIntegers(ref Integer[] A)
    {
      int sum = 0;
      for (int i=0; i<A.Length; i++)
      {
        sum += A[i].value;
      }
      return sum;
    }

    static void Main(string[] args)
    {
      // Передача out-масиву екземплярів класу в метод

      // 1. Оголосити масив типу Integer
      const int MAX_ITEMS = 8; // максимально-допустима к-сть елементів у масиві
      Integer[] Array;

      // 2. Виділити пам'ять для MAX_ITEMS елементів, сформованих випадково
      Array = new Integer[MAX_ITEMS];

      // 3. Виділити пам'ять для кожного елементу типу Integer
      for (int i = 0; i < Array.Length; i++)
        Array[i] = new Integer();

      // 4. Заповнити масив Array фіксованими  значеннями від 1 до MAX_ITEMS
      for (int i=0; i<Array.Length; i++)
      {
        Array[i].value = i + 1;
      }

      // 5. Вивести масив на екран в рядок
      Console.WriteLine("Items in Array:");
      for (int i=0; i<Array.Length; i++)
      {
        Console.Write($"{Array[i].value}\t");
      }

      // 6. Заповнити масив Array випадковими числами
      // з допомогою виклику функції GetArray()
      GetArrayOut(out Array); // функція статична, змінює масив всередині

      // 7. Вивести змінений масив на екран
      Console.WriteLine("\nArray after random forming:");
      for (int i=0; i<Array.Length; i++)
      {
        Console.Write($"{Array[i].value}\t");
      }

      // 8. Обчислити суму елементів зміненого масиву та вивести її на екран
      int summ = Program.SumIntegers(ref Array);
      Console.WriteLine($"\nsumm = {summ}");
    }
  }
}

Результат виконання програми:

Items in Array:
1 2 3 4 5 6 7 8
Array after random forming:
1 4 5 9 5 2
summ = 26

 

4. Передача двовимірного масиву екземплярів класу як ref-параметру. Приклад

У прикладі демонструється передача у функцію двовимірного масиву екземплярів класу як ref-параметру. Якщо потрібно реалізувати передачу у функцію двовимірного масиву як out-параметру, то модифікатор ref замінюється на модифікатор out.

У програмі реалізовано такі класи та методи:

  • клас Integer – реалізує ціле число;
  • статичний метод GetArray2D(), який отримує параметрами посилання на двовимірний масив A екземплярів класу Integer та посилання на змінні Rows, Columns (кількість рядків та кількість стовпців). У цьому методі виділяється пам’ять для масиву, формуються розміри та значення його елементів. Усі зміни всередині функції будуть відображатись у викликаючому коді (функції main());
  • статичний метод SumIntegers2D(), який отримує параметрами ref-посилання на масив та його розмірність. Метод обчислює суму елементів масиву;
  • статичний метод PrintArray2D(), який отримує масив та його розмірність за значенням (без модифікатора ref чи out). Даний метод виводить масив на екран.

Текст програми наступний

using System;

namespace ConsoleApp2
{
  // Клас Integer - посилальний тип
  class Integer
  {
    public int value;
  }

  class Program
  {
    // Статична функція GetArray2D() генерує (формує) масив випадкових чисел.
    // Масив передається як ref-параметр, можна змінювати саме посилання A.
    // Параметри Rows, Columns повертають к-сть стовпців та рядків масиву.
    static void GetArray2D(ref Integer[,] A, ref int Rows, ref int Columns)
    {
      // 1. Ініціалізувати генератор випадкових чисел
      Random rnd_num = new Random();

      // 2. Сформувати розмір масиву
      Rows = 3; // кількість рядків
      Columns = 4; // кількість стовпців

      // 3. Виділити пам'ять для двовимірного масиву в цілому
      A = new Integer[Rows, Columns];

      // 4. Виділити пам'ять для кожного екземпляру окремо
      for (int i = 0; i < Rows; i++)
        for (int j = 0; j < Columns; j++)
        {
          A[i, j] = new Integer();
        }

      // 5. Заповнити масив випадковими цілими числами в межах [0; 10]
      for (int i = 0; i < Rows; i++)
        for (int j = 0; j < Columns; j++)
        {
          // Усі зміни в масиві будуть відображатись за межами даної функції
          A[i, j].value = rnd_num.Next(0, 10);
        }

      // 6. Повернення з функції
      return;
    }

    // Статична функція, яка знаходить суму елементів двовимірного масиву.
    // Масив передається за посиланням (з модифікатором ref).
    // Параметри Rows, Columns передаються за значенням.
    static int SumIntegers2D(ref Integer[,] A, int Rows, int Columns)
    {
      int sum = 0;
      for (int i = 0; i < Rows; i++)
        for (int j = 0; j < Columns; j++)
        {
          sum += A[i, j].value;
        }
      return sum;
    }

    // Статична функція PringArray2D(), яка виводить двовимірний масив на екран.
    // Функція отримує масив A, розміри масиву m, n. Параметри передаються за значенням
    static void PrintArray2D(Integer[,] A, int m, int n)
    {
      for (int i = 0; i < m; i++)
      {
        for (int j = 0; j < n; j++)
        {
          Console.Write("{0}\t", A[i, j].value);
        }
        Console.WriteLine();
      }
    }

    static void Main(string[] args)
    {
      // Передача двовимірного ref-масиву екземплярів класу в метод

      // 1. Оголосити посилання на двовимірний масив типу Integer
      Integer[,] Array2D = null;
      // 2. Задати кількість рядків та стовпців у масиві
      int m, n;
      m = 2; // к-сть рядків
      n = 3; // к-сть стовпців

      // 3. Сформувати масив з допомогою функції GetArray2D()
      GetArray2D(ref Array2D, ref m, ref n);

      // 4. Вивести сформований масив на екран
      Console.WriteLine("Array2D:");
      PrintArray2D(Array2D, m, n);

      // 5. Обчислити суму елементів масиву та вивести її на екран
      int summ = SumIntegers2D(ref Array2D, m, n);
      Console.WriteLine($"summ = {summ}");
    }
  }
}

Результат роботи програми

Array2D:
5 1 7 6
7 7 8 9
7 2 3 7
summ = 69

 


Зв’язані теми