Ошибка в ассигновании переменных

Проблема - что, если я делаю:

ListaDeListas = {{"1","2","3"},{"4","5","6"},{"7","8","9"}...}

List<string> Lista = new List<string>();

Lista = ListaDeListas[0];

До сих пор все добро, тогда Вы, когда вслед за:

Lista.Add("1");
Lista.Add("2");
Lista.Add("3");

Здесь я подтверждаю значение ListaDeListas и Вы даете мне:

ListaDeListas = {{"1","2","3","1","2","3"},{"4","5","6"},{"7","8","9"}...}

Я понимаю, что в этом кодексе значение ListaDeListas Вы были бы должны пребывать неизменными, но, может быть, есть что-то, что теряло бы меня, или какое-то понятие, которое Вы считали бы ошибочным.

Почему происходит это?

5
задан 01.11.2019, 13:29
1 ответ

Ошибка в asignaciГіn переменных

BГЎsicamente не ошибка. Чтобы мочь подтверждать это, нужно понимать две концепции фиксируй: Типа ссылки и Типа стоимости .

Типа ссылки:

Способствует тому, чтобы каждый раз, когда мы использовали переменную, прошла ссылка.

Например:

using System;

class A
{
    public int b = 9;
}

class Program
{
    static void Main()
    {       
        A a = new A();  
        Console.Write(a.b);
        A c = a;
        c.b = 10;
        Console.Write(a.b);
    }
}

ВїPor quГ© дал как оказанный 10?

Это ему должно porquГ© его estГЎ перемещая ссылку первоначального объекта a на c. Но это возможное porquГ© идентификатор A - класс (классы в C# - тип ссылки ).

Давайте Анализировать cГіdigo по частям:

1. Уедь:

A a = new A();  

cГіdigo наверху того, что он делает, состоит в том, чтобы создавать объект и ему распределяется она direcciГіn основание объекта в указатель implГ - я упоминаю a. По умолчанию, признак b tendrГЎ хранившаяся стоимость 9.

2. Уедь:

Console.Write(a.b);
A c = a;

печатает на экране контент признака b (один 9) и ademГЎs этого, перемещают в указатель c ее его direcciГіn памяти, которая считала бы сохраняемым указатель a. Тогда, поскольку ты можешь видеть, у указателя c есть первоначальная ссылка объекта, на который указывал указатель a.

3. Уедь: Такой

c.b = 10;
Console.Write(a.b);

Как указатель implГ - упомянул c у него есть тот же контент a, я могу изменять признак первоначального объекта и из-за этой razГіn, печатает один 10, porquГ© указатели a и b, они указывают на тот же объект.

Типов стоимости:

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

Например:

using System;

struct A
{
    public int b;
    public A(int b)
    {
        this.b = b;
    }
}

class Program
{
    static void Main()
    {       
        A a = new A(9); 
        A c = a;
        c.b = 10;
        Console.Write(a.b);
    }
}

ВїPor quГ© дал как оказанный 9?

Это проистекает porquГ© estГЎ перемещая копию информации. Но это возможное porquГ© идентификатор A - структура (struct в C# - тип стоимости ).

Давайте Анализировать cГіdigo по частям:

1. Уедь:

A a = new A(9); 

cГіdigo наверху способствует тому, чтобы указатель a сослался на объект (где он envГ - в информацию в первого parГЎmetro строителя).

2. Уедь:

A c = a;

Это часть mГЎs важная, благодаря тому, что, не он estarГ - в перемещая ссылку первоначального объекта (в которое я указал на a), а mГЎs добро, estarГ - в создавая новый объект, он это означает, что указатель c tendrГЎ сохраняемый одна direcciГіn основание нового объекта (это не объект, который указывает на a). Тогда после новый объект был создан раньше, составитель берется за то, чтобы перемещать контент (признаки) первоначального объекта в новый объект (в который он указывает на c).

Для того, чтобы он остался mГЎs ясно, этот cГіdigo:

A c = a;

эквивалентный в:

A c = new A(0);
c.b = a.b;

Во втором cГіdigo отражается mГЎs, функционирование:

  • создает новый объект.

  • перемещают его копию данных, что tenГ - в предыдущий объект, в новый объект.

С этой explicaciГіn, podrГ-хозяева отвечать rГЎpidamente твое сомнение и тревогу.

В примере, который ты показал, estГЎs создавая список объектов, только, что каждый объект serГЎ типа List<string> (поэтому razГіn, ему говорится список списков, а именно, в списке, tendrГЎs несколько списков).

Тогда, как List - класс, serГЎ Тип ссылки .

cГіdigo, который ты показал:

Lista = ListaDeListas[0];

В действительности, что estГЎs происходя ahГ, - это та direcciГіn основание первого элемента, у которого был список объектов.

Каждое изменение, которое ты делаешь с указателем implГ, - упомянул Lista, он окажется отраженным в ListaDeListas[0]. Но ты darГ© пример mГЎs ясный для того, чтобы ты это понял лучше.

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {       
        List<string> list1 = new List<string>();
        List<string> list2 = new List<string>();
        List<string> list3 = new List<string>();

        List<List<string>> lists = new List<List<string>>();

        lists.Add(list1);
        lists.Add(list2);

        lists[0].Add("1");
        lists[0].Add("2");
        lists[0].Add("3");

        lists[1].Add("4");
        lists[1].Add("5");
        lists[1].Add("6");

        list3 = lists[0];
        list3.Add("1");
        list3.Add("2");
        list3.Add("3");

        foreach(string l in list3)
            Console.Write(l + "\n");

        Console.ReadLine();
    }
}

Это дает как результат:

1
2
3
1
2
3

ВїPor quГ© дал этот результат?

, Чтобы знать porquГ©, explicarГ© шаг за шагом, cГіdigo наверху.

1. Уедь:

List<string> list1 = new List<string>();
List<string> list2 = new List<string>();
List<string> list3 = new List<string>();

BГЎsicamente aquГ,, - где создает 3 список объектов типа string.

2. Уедь:

List<List<string>> lists = new List<List<string>>();
lists.Add(list1);
lists.Add(list2);

создает список объектов типа List<string> и despuГ©s, aГ±ade два объекта типа List<string>.

3. Уедь:

lists[0].Add("1");
lists[0].Add("2");
lists[0].Add("3");

lists[1].Add("4");
lists[1].Add("5");
lists[1].Add("6");

В этом cГіdigo уходит aГ±adiendo объекты типа string в два ты заносишь в список (list1 и list2), что estГ©n хранение в списке типа List<string>.

До того, как Гєltima объясняет, уезжает cГіdigo, чтобы отвечать на твое сомнение, ты dibujГ© форма как podrГ, - когда это, отраженное в памяти быть:

 B1:      
|0x0F| -> B2: |0x0F|0x04|0x05| 
|0xFF| -> B3: |0xFF|0x08|0x09| 

Блок 1 (B1) - список списков и каждый элемент tendrГЎ она direcciГіn основание списка объекта типа string.

Блок 2 (B2) - список типа string и каждый элемент tendrГЎ она direcciГіn основание объекта типа string.

Блок 3 (B3) - список типа string и каждый элемент tendrГЎ она direcciГіn основание объекта типа string.

3. Уедь:

list3 = lists[0];

В нашем mapita памяти, мы знаем, что lists[0] darГ - в как оказанный она direcciГіn 0x0F, bГЎsicamente эта та direcciГіn, что tendrГЎ сохраняемая указатель list3.

3 Уезжает:

list3.Add("1");
list3.Add("2");
list3.Add("3");

AquГ - aГ±adimos 3 объекта типа string в list3. Но если мы уходим в наш mapita памяти, estarГ-хозяев добавляя 3 адреса основания этих объектов в блоке 2.

Тогда, наш mapita становится отвечающим современным требованиям: Такие

 B1:     
|0x0F| -> B2: |0x0F|0x04|0x05|0x20|0x21|0x22| 
|0xFF| -> B3: |0xFF|0x08|0x09| 

Как блок 2 представляет список объектов, который манипулирует list3, estarГ-хозяина aГ±adiendo 3 базовыми адресами этих объектов в B2.

Сейчас, если мы печатаем контент блока 2 (который bГЎsicamente является блоком, который манипулирует указателями list3 и lists[0]), мы darГ - в как результат 123123.

Поэтому razГіn, печатает нам этот результат, как lists[0] считает сохраняемой ее direcciГіn 0x0F и list3 tambiГ©n считает хранившейся саму direcciГіn, тогда любое изменение verГЎ отраженный в B2 (в блоке 2 из нашего mapita памяти, которая bГЎsicamente как будто это был первый список объектов типа string).

4
ответ дан 01.12.2019, 14:44

Теги

Похожие вопросы