The_Unknown_Member Ответов: 2

[C#] возврат массива из метода ?


Привет. Я экспериментирую с возвращением массивов из метода, и у меня есть вопрос. Итак, давайте взглянем на код:
class Program
{
    static void Main()
    {
        string[] strArr = GetNames();
        strArr[0] = "Nik";
        string[] strArr2 = GetNames();
        Console.WriteLine("strArr[0] = {0} and strArr2[0] = {1}", strArr[0], strArr2[0]);
    }

    static string[] GetNames()
    {
        string[] ret = { "Matthew", "Mark", "Luke", "John" };
        return ret;
    }
}


Поскольку это ссылочный тип, и когда я создаю свой strarr string array и передаю ему возвращаемый массив из метода GetNames, и когда я изменяю первый элемент массива на другой, не должен ли он также изменить первый элемент в массиве метода ?

Что я уже пробовал:

Немного поэкспериментировал с ним и решил спросить Здесь.

PIEBALDconsult

Нет, строки в CLR имеют семантику типа значения - они неизменяемы.

2 Ответов

Рейтинг:
0

George Swan

Причина этой разницы заключается в том, что ваш GetNames метод создает новый массив каждый раз, когда он вызывается. Вы могли бы переписать его так


static string[] GetNames()
        {
            return new [] { "Matthew", "Mark", "Luke", "John" };
            
        }

Так strArr и strArr2 в вашем примере мы ссылаемся на разные массивы. Точка зрения о неизменности строк справедлива, но она не является причиной поведения, которое вы проиллюстрировали.


Рейтинг:
0

OriginalGriff

Это сложно. Массив-это ссылка, но это ссылка на массив ссылок. А строки-это особый случай, потому что они неизменяемы: однажды созданные, они не могут быть изменены, поэтому следующий код не обязательно делает то, что вы могли бы подумать:

string x = "XXX";
string y = x;
x = "YYY";
Console.WriteLine("{0}:{1}", x, y);
Это приведет к печати "YYY:XXX", потому что неизменяемость означает, что ссылка на строку действует как значение - вместо изменения существующего содержимого ссылки создается новая ссылка, так что старая строка вообще не изменяется.
Когда вы запускаете свой код, вы получаете аналогичный эффект:
string[] strArr = GetNames();
возвращает ссылку на массив строк.
string[] strArr2 = GetNames();
Также возвращает ссылку на массив строк.
Но... они не являются одной и той же ссылкой, потому что это не один и тот же массив!
Попробовать это:
if (strArr == strArr2) Console.WriteLine("Same");
else Console.WriteLine("Different");
Всегда будет печатать "разные", потому что, несмотря на то, что строки одинаковы, массивы-нет.

Каждый раз, когда вы выполняете этот код:
string[] ret = { "Matthew", "Mark", "Luke", "John" };
Фреймворк создает новый массив и заполняет его строками, которые вы должны вернуть.
Если вы хотите поделиться ими, вам нужно будет вернуть один и тот же массив:
static string[] ret = { "Matthew", "Mark", "Luke", "John" };
static string[] GetNames()
    {
    return ret;
    }
Теперь вы получите
strArr[0] = Nik and strArr2[0] = Nik
И "то же самое", если вы делаете сравнение.


The_Unknown_Member

Это немного сбивает с толку

OriginalGriff

Возможно , но это имеет смысл, когда вы об этом думаете.
Что тебе не понятно?

The_Unknown_Member

Эта вещь:

статическая строка[] ret = {"Матфей", "Марк", "Лука", " Иоанн" };
статическая строка [] GetNames()
{
вернуться в отставке;
}

OriginalGriff

Ну, вы использовали статику, так что вы знаете, что это делает.
А остальное копируется из вашего исходного кода, так что вы знаете, что это делает - вы его написали! :смеяться:

The_Unknown_Member

Я хотел спросить, почему, когда массив определен как статический и массив находится вне тела метода GetNames, почему метод может его возвращать ?

OriginalGriff

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

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