Словарные данные очищаются после добавления?

Это упрощенный код, почему все данные списка Tuple в моем словаре dict (кроме ключей) очищаются, когда я вызываю метод item.Clear()? Я не могу поместить параметр элемента в цикл for, так как это часть гораздо более сложного вложенного цикла.

var dict = new Dictionary<string, List<Tuple<string, string>>>();
var item = new List<Tuple<string, string>>();

for (int i = 0; i < 5; i++)
{
    item.Add(new Tuple<string, string>("key1", $"itemKey{i.ToString()}"));
    item.Add(new Tuple<string, string>("key2", $"itemKey{i.ToString()}"));
    item.Add(new Tuple<string, string>("key3", $"itemKey{i.ToString()}"));
    item.Add(new Tuple<string, string>("key4", $"itemKey{i.ToString()}"));
    dict.Add($"dictKey{i.ToString()}", item);
    item.Clear();
}

c#
person Daniel Tay    schedule 10.04.2019    source источник
comment
Вы добавляете ссылку на item в словарь, а затем очищаете item. Почему бы вместо этого не установить item в новую ссылку?   -  person    schedule 10.04.2019
comment
У вас есть 'item.Clear();' как последняя операция в цикле. Он очищает список. Здесь вы можете упустить основные различия между типами Reference и Value. Строка не является хорошим учителем для них, так как это ссылочный тип, который намеренно ведет себя как тип значения.   -  person Christopher    schedule 10.04.2019
comment
@Christopher Нет, строка вообще не ведет себя как тип значения. Он ведет себя точно так же, как ссылочный тип, поскольку является ссылочным типом. Он никоим образом не ведет себя как тип значения, потому что это не тип значения.   -  person Servy    schedule 10.04.2019
comment
@Servy Тогда у вас есть очень странные ссылочные типы, которые всегда используют равенство значений поверх равенства ссылок.   -  person Christopher    schedule 10.04.2019
comment
@ Кристофер Это совсем не странно. Для ссылочных типов очень часто используется равенство значений, а не ссылка. Очень редко полезно иметь равенство типа по умолчанию для ссылок. Просто фреймворк не может сам по себе обеспечить эффективное равенство значений. Но вы должны делать это самостоятельно для любого типа, у которого есть реальная возможность вообще сравниваться на равенство, независимо от того, является ли он типом значения или ссылочным типом.   -  person Servy    schedule 10.04.2019
comment
@Servy: ссылочные типы очень часто используют равенство значений, а не ссылку. Список? Тупель? Словарь? SQLConnections? Форма? Окно? Каждый пользовательский класс, в котором вы не переопределили процедуры сравнения? Я почти уверен, что ни один из этих обильно распространенных типов ссылок не использует равенство значений.   -  person Christopher    schedule 10.04.2019
comment
@Christopher Tuples do используют равенство значений. Я никогда не видел, чтобы кто-то сравнивал список или словарь по ссылке. Любой, кого я когда-либо видел, нуждающийся в сравнении их на равенство, хотел равенства значений и был вынужден создать собственный компаратор, который сравнивает их значения. То, что они не сравнивают значения по умолчанию, является ошибкой, на мой взгляд. SqlConnections, формы и окна почти никогда не сравниваются на равенство, потому что у них нет разумного определения равенства для использования, поэтому они просто сохраняют значение по умолчанию, потому что оно никогда не используется.   -  person Servy    schedule 10.04.2019
comment
@Servy А, так это обычное дело, потому что вы игнорируете все случаи, когда Value Equality и Inmutabiltiy не используются. Да, с таким определением это логично.   -  person Christopher    schedule 10.04.2019
comment
@Christopher Я никогда не говорил, что все ссылочные типы используют равенство значений или что все типы значений неизменяемы. Я сказал, что обычно используется равенство значений со ссылочными типами, что так и есть. Ссылочные типы также часто бывают неизменяемыми. Ссылочный тип, являющийся неизменяемым или использующий семантику значения для равенства, не делает его типом значения. Это по-прежнему ссылочный тип, он ведет себя как ссылочный тип, а не как тип значения. Равенство и изменчивость полностью независимы от того, имеет ли тип семантику значения или ссылки.   -  person Servy    schedule 10.04.2019
comment
@Christopher Точно так же, как ссылочный тип может сравнивать базовые значения типа на равенство или быть неизменяемым, тип значения не может не использовать базовые значения при сравнении на равенство или быть изменяемым. Потому что, опять же, эти две концепции независимы от семантики значения/ссылки.   -  person Servy    schedule 10.04.2019
comment
@Servy: я сказал, что обычно используется равенство значений со ссылочными типами, что и есть. Покажите мне проект. Подсчитайте, сколько ссылочных типов являются неизменяемыми. Подсчитайте, сколько ссылочных типов используют равенство значений. Затем я делаю то же самое. Тогда мы, возможно, сможем выяснить, каков процент вашего определения common.   -  person Christopher    schedule 10.04.2019
comment
@Christopher И что это покажет? Это не делает string больше типом значения или меньше ссылочным типом? Сказав это, я был бы более чем счастлив сравнить количество ссылочных типов, которые фактически используются для сравнения равенства, которые используют свою ссылку в качестве своей идентичности, с теми, которые используют значения внутри типа для своей идентичности. . Я почти никогда не видел, чтобы ссылка фактически использовалась в качестве идентификатора для целей равенства. Он используется только методами Equals типов, которые фактически не сравниваются на равенство, потому что это значение по умолчанию.   -  person Servy    schedule 10.04.2019
comment
@Servy: И что это покажет? Ваше определение, мое определение и определение читателей «Общего» совпадают? Вы знаете, полезный вклад в эту платформу обмена идеями? Скорее, вы звучите так, как будто вы можете не соглашаться только до тех пор, пока ваши определения неоднозначны?   -  person Christopher    schedule 10.04.2019
comment
@Christopher Но это не меняет того, имеют ли переменные string семантику ссылки или значения. То, что я думаю, что количество ссылочных типов, которые используют семантику равенства для равенства, является обычным явлением, не меняет того факта, что все они по-прежнему имеют ссылочную семантику и что переменные типа значения имеют семантику значения. То, как тип определяет равенство, не имеет отношения к тому, являются ли переменные этого типа ссылками или значениями. Что, конечно, было целью с самого начала. Меня не волнует, считаете ли вы, что тип редко использует свои значения для равенства, поскольку это не является важным моментом.   -  person Servy    schedule 10.04.2019


Ответы (1)


Когда вы вызываете dict.Add($"dictKey{i.ToString()}", item);, в словарь добавляется ссылка на объект. Поскольку вы очищаете список элементов, словарь также очищается.

Изменение кода на dict.Add($"dictKey{i.ToString()}", new List<Tuple<string, string>>(item)); не приведет к удалению записей из словаря, поскольку в словарь добавляется копия списка.

person Tejus    schedule 10.04.2019