Не нужно. Ваш основной метод передал массив этому методу, этот метод заполнил его. Ему не нужно возвращать его, потому что объект, на который указывает ваша переменная name, является тем же объектом, на который указывает исходная переменная в основном методе; в вашем основном методе уже есть все данные массива:
static void Main(){
var x = new string[10];
MyMethod(x);
Console.Write(x[0]); //prints "Hello"
}
static void MyMethod(string[] y){
y[0] = "Hello";
}
В этом демонстрационном коде выше мы начинаем с массива размером 10, на который ссылается переменная x. В памяти это выглядит так:
x --refers to--> arraydata
Когда вы вызываете MyMethod и передаете x, c# создаст другую ссылку y, которая указывает на те же данные:
x --refers to--> arraydata <--refers to-- y
Теперь, потому что обе ссылки указывают на одну и ту же область памяти. Все, что вы делаете с y, также влияет на то, что видит x. Вы помещаете строку (как я сделал с Hello) в слот 0, и x, и y ее видят. Когда MyMethod завершает работу, ссылка y отбрасывается, но x сохраняется и видит все изменения, внесенные вами при работе с y
Единственное, что вы не можете сделать, это указать y на другой объект массива в другом месте в памяти. Это не изменит x. Вы не можете этого сделать:
static void MyMethod(string[] y){
y = new string[20];
}
Если вы сделаете это, ваша полезная ссылка на x и y, указывающая на одну и ту же область памяти:
x ---> array10 <--- y
изменится на:
x ---> array10 y ---> array20
И тогда весь array20 и ссылка y будут отброшены, когда MyMethod завершится.
То же правило применяется, если вы вызываете метод, который предоставляет вам массив:
static void MyMethod(string[] y){
y = File.ReadAllLines("some path"); //this also points y away to a new array made by ReadAllLines
}
Не имеет значения, как и кто создает новый массив. Просто помните, что вы можете возиться с содержимым объекта, на который указывает y, сколько угодно, и изменения будут видны x, но вы не можете изменить весь объект, на который указывает y, и надеяться x увидит это
, в этом случае вам нужно будет вернуть его, когда вы закончите:
static string[] MyMethod(string[] y){
y = new ...
return y;
}
И основной метод должен будет зафиксировать изменение:
Main(...){
string[] x = new string[10];
string[] result = MyMethod(x);
}
Сейчас, пока я провожу этот мини-урок по «передаче по ссылке» и «передаче по значению» (который должен был называться «передача по исходной ссылке» и «передача по копии ссылки» ) было бы полезно отметить, что - это способ что-то изменить, чтобы MyMethod мог заменить y на совершенно новый объект, и x тоже увидит изменение.
На самом деле мы этим никогда не пользуемся; в этом редко возникает необходимость. Почти единственный раз он используется в таких вещах, как int.Parse
. Я говорю вам для полноты, если образование, чтобы, если вы столкнетесь с этим, вы это поймете, но вы всегда должны предпочесть подход «изменить содержимое, но не весь объект» или подход «если вы заставляете новый объект передавать его обратно»
Помечая аргумент y ключевым словом ref, c# не будет делать копию ссылки при вызове метода, он будет использовать исходную ссылку и временно позволит вам назвать ее y:
static void MyMethod(ref string[] y){
y = new array[20];
}
Наша диаграмма:
x ---> array10data
Временно становится:
x a.k.a y ---> array10data
Итак, если вы указываете y на новый массив, x тоже претерпевает изменение, потому что это одна и та же ссылка ; y больше не является другой ссылкой на одни и те же данные
x a.k.a y ---> array20data
Как я уже сказал, не используйте его - мы всегда стараемся избегать его по разным причинам.
Итак, я сказал в начале «вам не нужно» - под этим, и по указанным выше причинам я имел в виду , вам не нужно ничего возвращать из этого метода
Ваш метод получает массив, который он должен заполнить (из файла) в качестве параметра; он нигде не создает новый массив, поэтому нет необходимости возвращать массив по завершении. Он просто поместит любую строку длиной более 4 символов в слот массива. Затем он может завершить sh, ничего не возвращая, и метод, который вызвал этот метод, увидит изменения, внесенные им в массив. Это похоже на мой код, где MyMethod изменяет слот 0 в массиве, MyMethod был объявлен как void
, поэтому ему не нужно было делать оператор возврата, и мой бог основного метода все еще мог видеть Hello, которое я вставил в массив. Точно так же ваш метод Main будет видеть все эти строки из файла, если вы создадите свой метод ReadFileName (который, возможно, следует назвать FillArray), потому что он заполняет массив с именем name
Самое полезное, что ваша метод может возвращать целое число, указывающее, сколько строк было прочитано; переданный массив имеет фиксированный размер. Вы не можете изменить его размер, потому что это влечет за собой создание нового массива, который не будет работать по всем тем причинам, о которых я говорил выше. Если бы вы создали новый массив и вернули его, в передаче массива не было бы никакого смысла.
Таким образом, есть несколько способов улучшить этот код, но, на мой взгляд, их всего два:
- не передавать массив; пусть этот метод создаст новый массив и вернет его. Новый переданный массив может иметь точный размер, чтобы соответствовать
- с учетом идеи «передать массив в» и вернуть целое число, показывающее, сколько строк было фактически прочитано вместо
Для Вторая идея (которая является самой простой для реализации) вам нужно изменить тип возвращаемого значения на int:
static int ReadFileName(string[] name)
И вы должны вернуть ту переменную, которую вы используете, чтобы отслеживать, в какой слот вставить следующую вещь, counter . Счетчик всегда на 1 больше, чем количество сохраненных вами вещей, поэтому:
return counter - 1;
Теперь ваш метод вызова может выглядеть так:
string[] fileData = new string[10000]; //needs to be big enough to hold the whole file!
int numberOfLinesRead = ReadFileName(fileData);
Теперь вы понимаете, почему ReadFileName является плохая репутация метода? Было бы лучше назвать его FillArrayFromFile. Эта последняя строка кода не читается как книга, она не имеет смысла с точки зрения естественного языка. Зачем тому, что выглядит так, как будто оно читает имя файла (если это даже имеет смысл), брать массив и возвращать int - вызов его ReadFileName заставляет его звучать больше, как будто он ищет массив для имени файла и возвращает номер слота, в котором он был найден Здесь заканчивается фраза «назовите свои методы соответствующим образом 101»
Итак, другая идея заключалась в том, чтобы метод Read создавал свой собственный массив и возвращал его. Пока мы на нем, назовем его ReadFileNamed и попросим указать путь к файлу, чтобы его не было жестко закодировано для чтения только этого одного файла. И мы заставим его вернуть массив
static string[] ReadFileNamed(string filepath)
^^^^^^^^ ^^^^^^^^^^^^^^^
the return type the argument passed in
Сделайте так, чтобы первое, что он сделал, - объявил массив, достаточно большой для хранения файла (с этой идеей все еще есть проблемы, но это программирование 101; Я позволю им go. Не могу исправить все, используя то, чему вас еще не учили)
Поместите это где-нибудь разумно:
string lines = new string[10000];
И измените все ваши вхождения Вместо этого «name» будет «строками» - снова мы называем наши переменные точно так же, как мы разумно называем наши методы
Измените строку, которая читает фиксированное имя файла, чтобы использовать имя переменной, которое мы передаем ..
using (StreamReader file = new StreamReader(filepath))
В конце метода единственное, что остается сделать, это точно определить размер массива, прежде чем мы его вернем. Для 49-строчного файла счетчик будет 50, поэтому давайте сделаем массив размером 49, а затем заполним его, используя al oop (я сомневаюсь, что вам показали Array.Copy)
string[] toReturn = new string[counter-1];
for(int x = 0; x < toReturn.Length; x++)
toReturn[x] = lines[x];
return toReturn;
И теперь назовите это так:
string[] fileLines = ReadFileNamed("student marks.txt");