В .NET Framework многие классы System.Collection имеют методы Clear
. Есть ли явное преимущество при использовании этого вместо замены ссылки на новый объект?
Спасибо.
В .NET Framework многие классы System.Collection имеют методы Clear
. Есть ли явное преимущество при использовании этого вместо замены ссылки на новый объект?
Спасибо.
Вы хотите использовать Clear
, если у вас есть другие ссылки на один и тот же объект, и вы хотите, чтобы все они указывали на один и тот же объект.
Например, возможно, у вас есть рабочая очередь, где хранятся задачи. И в одном или нескольких потоках вы берете рабочие элементы из этой очереди (конечно, вы используете блокировку, чтобы убедиться, что вы обращаетесь к очереди с не более чем одним потоком за раз). Если в какой-то момент вы хотите очистить очередь, то вы можете использовать Clear
, и все потоки будут по-прежнему указывать на один и тот же объект.
В качестве здесь видно, когда вы используете Clear
, все элементы будут удалены, а Count
будет 0, но Capacity
останется неизменным. Обычно Capacity
остается неизменным - это хорошо (для эффективности), но может быть какой-то крайний случай, когда у вас было много предметов, и вы хотите, чтобы память была в конечном итоге освобождена.
В приведенной выше ссылке MSDN также упоминается, что Clear является операцией O (n). Если просто заменить ссылку будет операция O (1), а затем, в конце концов, это будет сбор мусора, но, возможно, не сразу. Но замена ссылки также означает, что память, которая составляет емкость, должна быть перераспределена.
Брайан прав, но, более конкретно, метод Clear
удаляет все элементы из текущего экземпляра коллекции. Создание экземпляра новой коллекции и присвоение ее ссылки на вашу переменную даст вам совершенно новый экземпляр в целом и может привести к некоторым непредвиденным последствиям в зависимости от того, ссылаются ли другие люди на старый экземпляр. Если в другом потоке есть ссылка на эту коллекцию, они все равно будут содержать ссылку на старую коллекцию, даже если вы создали новый экземпляр.
замена ссылки не приведет к немедленному освобождению коллекции, ей нужно будет дождаться, когда сборщик мусора удалит объект,
если вы хотите повторно использовать один и тот же набор объектов, используйте 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 файла.