Различия между Dictionary.Clear и новым Dictionary()
-
05-07-2019 - |
Вопрос
Каковы ключевые различия между Dictionary.Clear
и new Dictionary()
на С#?Какой из них рекомендуется в каких случаях?
Решение
Dictionary.Clear ()
удалит все пары KeyValue
в словаре. Выполнение new Dictionary ()
создаст новый экземпляр словаря.
Если и только если старая версия словаря не укоренена в другой ссылке, создание нового словаря сделает весь словарь и его содержимое (не находящееся в другом месте) доступным для очистки GC. р>
Dictionary.Clear ()
сделает пары KeyValue
доступными для очистки.
На практике оба варианта будут иметь очень похожие эффекты. Разница будет в том, что происходит, когда это используется внутри метода:
void NewDictionary(Dictionary<string,int> dict)
{
dict = new Dictionary<string,int>(); // Just changes the local reference
}
void ClearDictionary(Dictionary<string,int> dict)
{
dict.Clear();
}
// When you use this...
Dictionary<string,int> myDictionary = ...; // Set up and fill dictionary
NewDictionary(myDictionary);
// myDictionary is unchanged here, since we made a new copy, but didn't change the original instance
ClearDictionary(myDictionary);
// myDictionary is now empty
Другие советы
Как уже было подробно рассмотрено, эффекты практически одинаковы. И Clear ()
, и new
дадут вам новый словарь, по сути, оставляя ссылки на объекты внутри него, освобождая их для сбора, если они стали неутвержденными. р>
Технически, .Clear ()
будет иметь преимущество перед new
, если вы собираетесь заполнить словарь до того же размера, что и раньше. Это потому, что он уже был бы изменен внутри, чтобы вместить количество объектов, которые у вас были в нем ранее. Создание нового словаря будет иметь новую внутреннюю хеш-таблицу с размером по умолчанию, и его придется расширять по мере добавления элементов в него.
Я также хотел бы предложить, чтобы они сообщали совершенно другое намерение, и вы должны использовать .Clear ()
в своем коде, когда вы имеете дело с тем же контекстом, что и раньше. Создание нового Словаря подразумевает, что вы собираетесь приступить к некоторой новой логике, имеющей дело с чем-то отличным от старого Словаря, в то время как использование Clear ()
указывает, что да, вы действительно хотели просто сбросить все, что вы сделано до сих пор с этим.
Словарь.Очистить()
Это приведет к удалению всех пар ключ/значение из словаря.Сборщик мусора очистит память для этих элементов во время следующего цикла сбора мусора. MSDN
новый словарь()
Создает новый объект Dictionary в памяти и удаляет исходный объект.Память будет очищена во время следующего цикла сборки мусора.
Я предполагаю, что ключевое отличие состоит в том, что если вы вызовете Dictionary.Clear ()
, все ссылки на этот словарь будут удалены. Если вы используете new Dictionary ()
, то ссылка, с которой вы имеете дело в то время, будет очищена (в некотором смысле), но все остальные места, на которые у вас есть ссылки, не будут, так как они все еще будут ссылаясь на старый словарь.
Надеюсь, этот код иллюстрирует это просто:
public void Method()
{
Dictionary<int, int> d1 = new Dictionary();
d1.Add(1,1);
d1.Add(2,3);
Dictionary<int, int> d2 = d1;
//this line only 'clears' d1
d1 = new Dictionary();
d1.Add(1,1);
d1.Add(3,5);
d2.Add(2,2);
//writes '2' followed by '1'
Console.WriteLine(d1.Count);
Console.WriteLine(d2.Count);
}
Если бы я вместо этого вызвал d1.Clear ()
, то d1 и d2 остались бы в синхронизации, и последующие добавления добавили бы к обоим. Оба вызова WriteLine вместо этого будут иметь «3».
Dictionary.Clear
удалит (но не удалит) все элементы в экземпляре, тогда как new Dictionary ()
создаст новый экземпляр, который просто окажется пустым. Там могут быть некоторые тонкие последствия между ними. Рассмотрим следующие примеры.
void Example1()
{
var collection = new Dictionary<string, string>();
collection.Add("key1", "value1");
collection.Add("key2", "value2");
foreach (var kvp in collection)
{
collection = new Dictionary<string, string>();
Console.WriteLine(kvp);
}
}
void Example2()
{
var collection = new Dictionary<string, string>();
collection.Add("key1", "value1");
collection.Add("key2", "value2");
foreach (var kvp in collection)
{
collection.Clear();
Console.WriteLine(kvp);
}
}
В первом примере будет напечатано все содержимое оригинальной коллекции. Это связано с тем, что перечислитель был создан из ссылочной переменной до того, как он был переназначен новому экземпляру.
Во втором примере коллекция очищается во время перечисления, что приводит к InvalidOperationException
, поскольку коллекция была изменена.
Я полагаю, что .Clear () был предоставлен для того, чтобы, если ваш словарь отображался как свойство только для чтения, вы могли удалить все элементы. Однако, если это не раскрыто таким образом, и вы имеете полный контроль, тогда может быть проще просто создать новый словарь. Между ними также может быть небольшая разница в производительности.
Если у вас есть несколько ссылок на этот словарь, и вы очистите его, вы будете влиять на них все, где, как если бы вы создали новый словарь, вы будете влиять только на одну новую ссылку. Я думаю, это зависит от масштаба воздействия, к которому вы стремитесь. Очевидно, что вызов "нового" даст вам "очищено" словарь, но вы можете потерять другую полезную информацию о состоянии.
Dictionary.clear исключит все элементы в вашем словаре. Новый словарь создает новый объект словаря в памяти, в то же время осиротев прежний словарь, чтобы сборщик мусора мог его очистить позже.