В .NET Framework многие классы System.Collection имеют методы Clear
. Есть ли явное преимущество при использовании этого вместо замены ссылки на новый объект?Использование метода «clear» и New Object
Спасибо.
В .NET Framework многие классы System.Collection имеют методы Clear
. Есть ли явное преимущество при использовании этого вместо замены ссылки на новый объект?Использование метода «clear» и New Object
Спасибо.
Вы хотите использовать Clear
, если у вас есть другие ссылки на один и тот же объект, и вы хотите, чтобы все они указывали на один и тот же объект.
Возможно, у вас есть рабочая очередь, где хранятся задачи. И в одном или нескольких потоках вы берете рабочие элементы из этой очереди (конечно, вы используете блокировку, чтобы убедиться, что вы обращаетесь к очереди с не более чем одним потоком за раз). Если в какой-то момент вы хотите очистить очередь, тогда вы можете использовать Clear
, и все потоки будут по-прежнему указывать на один и тот же объект.
Как seen here при использовании Clear
все элементы будут удалены, а Count
будет 0, но Capacity
останется неизменным. Обычно Capacity
не меняется, это хорошая вещь (для эффективности), но может быть какой-то крайний случай, когда у вас было много предметов, и вы хотите, чтобы память была в конечном итоге освобождена.
В приведенной выше ссылке MSDN упоминается, что Clear является операцией O (n). Если просто заменить ссылку будет операция O (1), а затем, в конце концов, это будет сбор мусора, но, возможно, не сразу. Но замена ссылки также означает, что память, которая составляет емкость, должна быть перераспределена.
Это получило большую часть, единственное, что я хочу добавить, это то, что вы хотите использовать Clear при работе с ObservableCollections, которые просматриваются уже. – Rangoric
замена ссылки не выпустит коллекцию сразу, что нужно будет ждать, пока сборщик мусора расположить объект,
если вы хотите повторно использовать один и тот же объект коллекции использование ясно, если вы не будете иметь два объектов в памяти в течение некоторого времени.
Хотя это правда, это не та разница, о которой заботятся большинство людей. –
@ Игнасио Васкес-Абрамс зависит. Мне было бы очень интересно, если коллекция очень большая. – nawfal
Brian является правильным, но, если быть более конкретным, метод Clear
удаляет все элементы из текущего экземпляра коллекции. Создание экземпляра новой коллекции и присвоение ее ссылки на вашу переменную даст вам совершенно новый экземпляр в целом и может привести к некоторым непредвиденным последствиям в зависимости от того, ссылаются ли другие люди на старый экземпляр. Если в другом потоке есть ссылка на эту коллекцию, они все равно будут содержать ссылку на старую коллекцию, даже если вы создали новый экземпляр.
Это зависит от того, насколько велик ваш объект коллекции. Я думаю, когда вы скажете новое, он создаст исходный размер объекта, ясность просто очистит контент, но размер будет по-прежнему остальным.
Новый объект вызывает проблемы с памятью, если вы работаете с большими данными и часто используете элемент IEnumerable. Посмотрите на мой пример:
class Lol
{
int i;
string s;
public Lol(int ti, string ts)
{
i = ti;
s = ts;
}
}
class Program
{
static List<Lol> lol = new List<Lol>();
static void Main(string[] args)
{
for (int i = 0; i < 10000000; ++i)
lol.Add(new Lol(i, i.ToString()));
Stopwatch sw = new Stopwatch();
sw.Start();
ListCleaner();
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
for (int i = 0; i < 10000000; ++i)
lol.Add(new Lol(i, i.ToString()));
Console.WriteLine("lol");
ListCleaner();
for (int i = 0; i < 10000000; ++i)
lol.Add(new Lol(i, i.ToString()));
Console.WriteLine("lol");
ListCleaner();
for (int i = 0; i < 10000000; ++i)
lol.Add(new Lol(i, i.ToString()));
Console.WriteLine("lol");
ListCleaner();
for (int i = 0; i < 10000000; ++i)
lol.Add(new Lol(i, i.ToString()));
Console.WriteLine("lol");
ListCleaner();
for (int i = 0; i < 10000000; ++i)
lol.Add(new Lol(i, i.ToString()));
Console.WriteLine("lol");
ListCleaner();
for (int i = 0; i < 10000000; ++i)
lol.Add(new Lol(i, i.ToString()));
Console.WriteLine("lol");
ListCleaner();
for (int i = 0; i < 10000000; ++i)
lol.Add(new Lol(i, i.ToString()));
Console.WriteLine("lol");
ListCleaner();
for (int i = 0; i < 10000000; ++i)
lol.Add(new Lol(i, i.ToString()));
Console.WriteLine("lol");
ListCleaner();
}
static void ListCleaner()
{
//lol = new List<Lol>();
lol.Clear();
}
}
Если вы используете это, вы не столкнетесь с какой-либо проблемой во время выполнения. Но если вы прокомментируете строку «Очистить» в ListCleaner и раскомментируете новую линию объектов, у вас будет проблема с памятью.
Кстати, «Console.WriteLine (sw.ElapsedMilliseconds)»; (Вы можете использовать ElapsedTicks, потому что его значение сильно отличается от другого.) Строка говорит вам, что Clear занимает больше времени, но экономит вас от проблемы с памятью.
Я заметил, что все это происходит на отладочном коде (даже для режима выпуска). Нет проблем с запуском .exe-файла.
Возможный дубликат [Каковы основные различия между Dictionary.clear и новым Dictionary() в C#?] (Http://stackoverflow.com/questions/1400532/what-are-the-key-differences-between- dictionary-clear-and-new-dictionary-in-c) – nawfal