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