У слеці виникло питання:
using System;
namespace Arrays
{
class ArraysCopy
{
public static void Main(string[] args)
{
double[] myArray = GetNumbersFromConsole();
for (int i = 0; i < myArray.Length; ++i)
Console.WriteLine(myArray[i]);
}
static double[] GetNumbersFromConsole()
{
int count = int.Parse(Console.ReadLine());
double[] result = new double[count];
for(int i = 0; i < count; ++i)
{
result[i] = double.Parse(Console.ReadLine());
}
return result;
}
}
}
Хочу звернути увагу на те що масив копіюється два рази у вкладенці “порівняння”.
Зверху мій код. Знизу код Кодізі.
Ось строка котру я пропустила double[] copy = new double[myArray.Length];
using System;
namespace Arrays
{
class ArraysCopy
{
public static void Main(string[] args)
{
double[] myArray = GetNumbersFromConsole();
double[] copy = new double[myArray.Length];
for (int i = 0; i < myArray.Length; ++i)
copy[i] = myArray[i];
for (int i = 0; i < myArray.Length; ++i)
Console.WriteLine(copy[i]);
}
static double[] GetNumbersFromConsole()
{
int count = int.Parse(Console.ReadLine());
double[] result = new double[count];
for(int i = 0; i < count; ++i)
{
result[i] = double.Parse(Console.ReadLine());
}
return result;
}
}
}
double[] myArray = GetNumbersFromConsole();
ця строчка кода не “Копіює” масив (array), а створює його і він існує в одному екземплярі.
Масиви це “reference type” (посилання), а не “value type” (значення). Саме тому, посилання яке було створенно в середині метода GetNumbersFromConsole було передано в змінну “myArray”.
Нам же треба зробити копію масиву. В більшості випадків, коли програмісти кажуть “копіювати”, вони мають на увазі “копіювати значення”. Рішення кодізі саме це і робить. Ми створюємо новий масив такої самої довжини і копіюємо значення кожного елементу.
Спробуйте порівняти 2 варіанти методу Main. В першому варіанті ми створюємо новий масив копіювавши кожний елемент.
public static void Main(string[] args)
{
double[] myArray = GetNumbersFromConsole();
double[] copy = new double[myArray.Length];
for (int i = 0; i < myArray.Length; ++i)
copy[i] = myArray[i];
// змініюємо значення першого елементу оригінального масиву
myArray[0] = 42;
Console.WriteLine("Let's output original array after we changed first element of original array:");
for (int i = 0; i < myArray.Length; ++i)
Console.WriteLine(myArray[i]);
Console.WriteLine("Let's output copy array after we changed first element of original array:");
for (int i = 0; i < myArray.Length; ++i)
Console.WriteLine(copy[i]);
}
В другому варіанті, ми кажемо що наш новий масив посилається на старий масив шляхом double[] copy = myArray;
public static void Main(string[] args)
{
double[] myArray = GetNumbersFromConsole();
double[] copy = myArray;
// змініюємо значення першого елементу оригінального масиву
myArray[0] = 42;
Console.WriteLine("Let's output original array after we changed first element of original array:");
for (int i = 0; i < myArray.Length; ++i)
Console.WriteLine(myArray[i]);
Console.WriteLine("Let's output copy array after we changed first element of original array:");
for (int i = 0; i < myArray.Length; ++i)
Console.WriteLine(copy[i]);
}
3 Likes
Метод ніби зникає після завершення і більше не існує значень котрі він повернув, доки його не викличуть знову? Тому myArray = це не копія, а єдиний існуючий масив після того як закінчився метод?
1 Like
Побачила різницю між прикладами.
Трішки не так, але близько. Існує таке поняття як “scope” - область дії.
В мові с# межі scope - це код між “{” та “}”.
Всі змінні value type (значення, як от int), які створенні в середині метода - існують лише в середині метода.
Всі змінні reference type (посилання, як от масиви), які створенні в середині метода, АЛЕ не використовуються назовні - існують лише в середині метода, ОДНАК якщо вони використовуються ззовні - таке посилання буде видно і в інших частинах коду.
В нашому випадку, в середині метода ми створюємо новий масив double[] result = new double[count];
. Оскільки ми його і вертаємо наззовні (return result;
) - то змінна double[] myArray = GetNumbersFromConsole();
отримає посилання на саме цей масив. (як ви вірно і сказали)
якщо ж ми викличемо цей метод знову - ми створимо НОВИЙ масив
3 Likes
Для аналогії:
Уявіть що масив це “стікер” (такий жовтий папірець для нотаток).
Кожного разу як ви викликаєте new double[number]
- ви відриваєте такий стікер і number
вказує скільки там є рядків для запису.
Ви можете записати в нього дані (result[0] = 23;
result[1] = 42;
). Так само ви можете взяти цей стікер і віднести в іншу кімнату (return result;
). Такий стікер з такими даними існує в одному екземплярі.
Якщо вам треба скопіювати стікер, ви не можете його просто “забрати”, вам потрібно взяти новий стікер (double[] copy = new double[myArray.Length];
) та записати в ньому такі самі дані як в оригінальному стікері
3 Likes
Здається зрозуміла, дякую)