Список <T>является указателем? - PullRequest
9 голосов
/ 18 октября 2011

Я заметил, что поведение List<T> отличается от другого простого объекта, например, String.Вопрос может показаться новичком, но это действительно поразило меня, потому что я думал, что List<T> были простыми объектами.

Возьмем, например, следующий код:

List<String> ls1 = new List<String>();
ls1.Add("a");
List<String> ls2 = ls1;
ls1.Add("b");

В конце ls1будет равен {"a", "b"} и так будет ls2.Это действительно отличается от поведения этого кода:

String s1 = "a";
String s2 = s1;
s1 = "b";

Где s1 в конце равно b, а s2 равно a.

Этоозначает, что List<T> на самом деле является указателем, верно?

Ответы [ 5 ]

7 голосов
/ 18 октября 2011

List<T> a ссылочный тип , так что да, он ведет себя как указатель.

String также является ссылочным типом, но строки являются неизменяемыми и ведут себя как типы значений (в отличие от ссылочных типов) в некоторых случаях, поэтому здесь возникает путаница.

Здесь есть хорошее объяснение, почему строка работает таким образом: В C #, почему String является ссылочным типом, который ведет себя как тип значения?

3 голосов
/ 18 октября 2011

Строка s1 = "b" фактически назначает новую ссылку на s1.s1 и s2 теперь ссылаются на два разных объекта.

Изменения в объекте List<string>, на которые ссылается ls1, видны через все ссылки на этот объект, включая ls2.Когда вы делаете ls2 = ls1, вы в основном говорите, что ls1 и ls2 относятся к одному и тому же объекту.Изменения в объекте через ссылочную переменную ls1 видны через ссылочную переменную ls2.

1 голос
/ 18 октября 2011

В C # они называются references, а не pointers.Вероятно, это одно и то же, за исключением того факта, что вы не можете привести их к целому числу для их печати, и минус арифметика указателя, которая запрещена.Технически они «непрозрачны», поэтому вы не должны (не должны) знать, как они работают.Очевидно, что эта непрозрачность нарушается, если вы используете Managed C ++: -)

0 голосов
/ 18 октября 2011

String, int, float - все типы значений.Поэтому, когда вы говорите

String s1 = "a";
String s2 = s1;
s1 = "b";

Когда инициализируется s2, значение s1 равно , скопировано в пространство, выделенное для s2.Таким образом, если вы отслеживаете память, вы можете найти шестнадцатеричное представление «a» в двух различных местах в памяти (местоположение, выделенное для s1, и память, выделенное для s2).Но если вы попытаетесь сделать то же самое со ссылочным типом, таким как List, то, что произойдет, когда вы скажете что-то вроде этого, будет передача по ссылке:

List<String> ls1 = new List<String>();
ls1.Add("a");
List<String> ls2 = ls1;
ls1.Add("b");

, если объект, соответствующий списку, выделен накучаАдрес, где найти этот объект, находится в пространстве, выделенном для локальных переменных s1 и s2, вместо фактического значения, находящегося в этом пространстве.Причина в том, что объект (List) может быть большим и потенциально долгое время жизни программы, и для такого объекта было бы дорого выделять память вне стека.Я рекомендую вам прочитать эту ветку вопросов , чтобы понять, как типы значений и ссылочные типы действительно интерпретируются CLR

0 голосов
/ 18 октября 2011

Каждый объект в C # является ссылкой.Примитивы типа int, string , char, не являются ссылками.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...