Рейтинг:
1
lmoelleb
Первый шаг-исправить код, чтобы он компилировался.
Второй шаг-исправить код, чтобы он работал.
Третий шаг состоит в том, чтобы отладить его и наблюдать, что происходит.
Например, вы получите что-то вроде этого (используя консоль.WriteLine, конечно, вы бы использовали отладчик)
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Dictionary<int,string> dict_1 =new Dictionary<int, string>();
dict_1.Add(1,"a");
dict_1.Add(2,"b");
dict_1.Add(3,"c");
Dictionary<int, string> dict_2 =new Dictionary<int,string>(dict_1);
dict_1.Remove(1);//affects dict_2 also which should not happen.
Console.WriteLine(dict_1.Count);
Console.WriteLine(dict_2.Count);
}
}
Вы можете запустить его здесь:
Онлайн-компилятор C# | .NET Fiddle[
^]
Как и ожидалось, выходы 2 следуют за 3, поэтому явно содержание словарей отличается. Отладчик позволит вам наблюдать точное содержание словаря.
Рейтинг:
1
Graeme_Grant
Вот решение, которое позволит:
1. Создайте словарь и загрузите данные
2. резервное копирование (сериализация) словаря в строку, так как нам не нужно обращаться к нему
3. Удалите элемент
4. восстановление исходного словаря
class Program
{
static void Main(string[] args)
{
Console.WriteLine("-- start --");
var dict1 = new Dictionary<int, string>
{
[0] = "ABC",
[1] = "DEF",
[2] = "GHI",
};
foreach (var item in dict1)
Console.WriteLine($"{item.Key} = {item.Value}");
Console.WriteLine("-- serialize --");
var bkup = JsonConvert.SerializeObject(dict1);
Console.WriteLine(bkup);
Console.WriteLine("--remove item --");
dict1.Remove(1);
foreach (var item in dict1)
Console.WriteLine($"{item.Key} = {item.Value}");
Console.WriteLine("--restore --");
dict1 = JsonConvert.DeserializeObject<Dictionary<int, string>>(bkup);
foreach (var item in dict1)
Console.WriteLine($"{item.Key} = {item.Value}");
Console.ReadKey();
}
}
И выход есть:
-- start --
0 = ABC
1 = DEF
2 = GHI
-- serialize --
{"0":"ABC","1":"DEF","2":"GHI"}
--remove item --
0 = ABC
2 = GHI
--restore --
0 = ABC
1 = DEF
2 = GHI
Для этого примера я использовал библиотеку NewtonSoft JSON. Вы можете узнать больше об этой библиотеке здесь:
[
^]
Рейтинг:
0
BillWoodruff
Недавно я опубликовал пример слияния двух словарей, где в случае повторяющихся значений вы можете контролировать, какое значение используется в объединенном (новом) словаре [^]
Для того чтобы диктант2 был по-настоящему независимый из диктанта 1 вы должны сделать глубокий однако копирование пар KeyValuePairs, если ключи являются целыми числами, а значения строками, это легко, потому что задействованные типы не требуют реализации ICloneable.
Вы можете просто сделать это:
Dictionary<int, string> dict1 = new Dictionary<int, string>(dict2);
Вы ошибаетесь, когда утверждаете, что удаление KeyValuePair из dict1 повлияет на dict2.
lmoelleb
Будьте осторожны с ICloneable - он не указывает, является ли клон глубоким или мелким.
BillWoodruff
Поскольку я бы реализовал ICloneable только тогда, когда типы, которые я использовал, требовали глубокой копии, я не совсем понимаю, что вы здесь делаете. Пожалуйста, скажи больше.
lmoelleb
Реализация его в виде глубокой копии-это ваше предпочтение. Это не то, что предписано интерфейсом или его документацией (наоборот). Это означает, что каждый раз, когда вы видите интерфейс, вы должны думать: "это один из моих глубоких клонов, или я ссылаюсь на что-то написанное другим парнем, который мог бы сделать что-то еще". Для меня интерфейс просто не стоит использовать, когда мне приходится иметь дело с потенциальными будущими проблемами.
BillWoodruff
Реализация ICloneable не является предпочтением: это требование, когда вы хотите глубоко скопировать сложные, изменяемые объекты.
Это не единственный инструмент: вы можете использовать двоичную сериализацию. Я предлагаю вам изучить, что такое ICloneable и что это значит, а не фантазировать о воображаемых проблемах. В то время как MS предлагает ICloneable не использоваться в публичных API, это не имеет ничего общего с этим потоком.
https://docs.microsoft.com/en-us/dotnet/api/system.icloneable-что?redirectedfrom=MSDN&view=netframework-4.8
lmoelleb
Quoting from the very link you are providing: "It does not specify whether the cloning operation performs a deep copy, a shallow copy, or something in between". There is no built in interface that guaranties deep clones in .NET. Sure you can use ICloneable for it, just be aware that simply because an object implements ICloneable, you can't guarantie it is a deep copy without further information (you wrote it yourself, it is documented, you read the code, …). You call that an imaginary problem. I call it something to be aware of so it does not become a real problem. I have done my share of cloning, including everything from cloning in the constructor over ICloneable, custom IDeepCloneable etc all the way to emitted code with reflection. Can you please point me in the direction of what additional information I can study on this subject?
BillWoodruff
Боюсь, что мы находимся здесь на двух разных частотах, и я напрасно трачу время, пытаясь прояснить это :) То, что вы говорите, кажется мне одновременно очевидным и совершенно неуместным, учитывая, о чем идет речь в этой теме.
Реализация интерфейсов гарантирует только наличие структур с определенными сигнатурами: конечно, с ними можно сделать кровавую кашу.
Рейтинг:
0
George Swan
Если вы хотите обновить только те элементы, которые изменились, а не создавать новую копию при каждом обновлении, вы можете сделать что-то вроде этого.
var missingKeys = dictA.Where(p => !dictB.ContainsKey(p.Key));
var missingValues = dictA.Where(p => dictB.ContainsKey(p.Key) && dictB[p.Key]!=p.Value);
foreach(var p in missingKeys)
{
dictB.Add(p.Key, p.Value);
}
foreach (var p in missingValues)
{
dictB[p.Key]=p.Value;
}