Подтвердить что ты не робот

Использование метода "clear" и New Object

В .NET Framework многие классы System.Collection имеют методы Clear. Есть ли явное преимущество при использовании этого вместо замены ссылки на новый объект?

Спасибо.

4b9b3361

Ответ 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 файла.