Вопрос

Каковы ключевые различия между 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 исключит все элементы в вашем словаре. Новый словарь создает новый объект словаря в памяти, в то же время осиротев прежний словарь, чтобы сборщик мусора мог его очистить позже.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top