Как расположить класс в .NET?

вы можете сохранить исходную очередь во временную очередь. Затем вы просто выполняете обычную посылку во временной очереди, чтобы пройти через исходную, например:

queue tmp_q = original_q; //copy the original queue to the temporary queue

while (!tmp_q.empty())
{
    q_element = tmp_q.top();
    std::cout << q_element <<"\n";
    tmp_q.pop();
} 

В конце tmp_q будет пустым, но исходная очередь не тронута.

43
задан 8 revs, 7 users 44% 22 June 2016 в 15:16
поделиться

18 ответов

IDisposable не имеет никакого отношения к памяти освобождения. IDisposable является шаблоном для освобождения неуправляемый , ресурсы - и память являются вполне определенно управляемым ресурсом.

ссылки, указывающие на GC.Collect (), являются корректным ответом, хотя использованию этой функции обычно препятствует документация Microsoft.NET.

Редактирование: зарабатывавший значительное количество кармы для этого ответа, я чувствую определенную обязанность уточнить его, чтобы вновь прибывший к управлению ресурсами.NET не получает неправильное впечатление.

Внутренняя часть процесс.NET, существует два вида ресурса - управляются и неуправляемы. "Управляемый" означает, что время выполнения управляет ресурсом, в то время как "неуправляемый" средства, что это - ответственность программиста. И действительно существует только один вид управляемого ресурса, о котором мы заботимся в.NET сегодня - память. Программист говорит времени выполнения выделять память, и после этого это до времени выполнения для выяснения, когда память может освобожденный. Механизм, которым использование.NET с этой целью называют сборка "мусора" и можно найти много информации о GC в Интернете просто при помощи Google.

Для других видов ресурсов.NET ничего не знает о чистке их так, это должно полагаться на программиста, чтобы сделать правильную вещь. С этой целью платформа дает программисту три инструмента:

  1. интерфейс IDisposable и оператор "использования" в VB и финализаторах C#
  2. шаблон IDisposable, как реализовано многими классами BCL

первый из них позволяет программисту эффективно получать ресурс, использовать его и затем выпускать все это в рамках того же метода.

using (DisposableObject tmp = DisposableObject.AcquireResource()) {
    // Do something with tmp
}
// At this point, tmp.Dispose() will automatically have been called
// BUT, tmp may still a perfectly valid object that still takes up memory

, Если "AcquireResource" является методом фабрики, который (например), открывает файл и "Располагает" автоматически, закрывает файл, тогда этот код не может пропустить ресурс файла. Но память для самого объекта "tmp" может все еще быть выделена. Поэтому интерфейс IDisposable не имеет абсолютно никакого соединения со сборщиком "мусора". Если Вы сделали , хотят гарантировать, что память была освобождена, Ваша единственная опция будет состоять в том, чтобы звонить GC.Collect() для принуждения сборки "мусора".

Однако нельзя подчеркнуть достаточно, что это - вероятно, не хорошая идея. Обычно намного лучше позволить сборщику "мусора" сделать то, что это было разработано, чтобы сделать, который должен управлять памятью.

, Что происходит, если ресурс используется в течение более длительного промежутка времени, такого, что его продолжительность жизни пересекает несколько методов? Очевидно, оператор "использования" больше не применим, таким образом, программист должен был бы вручную звонить, "Располагают", когда он сделан с ресурсом. И что происходит, если программист забывает? Если нет никакой нейтрализации, то процесс или компьютер могут в конечном счете исчерпать, какой бы ни ресурс правильно не освобождается.

Это - то, где финализаторы входят. Финализатор является методом на Вашем классе, который имеет особые отношения со сборщиком "мусора". GC обещает, что - прежде, чем освободить память для любого объекта того типа - он сначала даст финализатору шанс сделать некоторую очистку.

Так в случае файла, мы теоретически не должны закрывать файл вручную вообще. Мы можем просто ожидать, пока сборщик "мусора" не добирается до него, и затем позвольте финализатору сделать работу. К сожалению, это не работает хорошо на практике, потому что сборщик "мусора" работает недетерминировано. Файл может остаться открытым значительно дольше, чем программист ожидает. И если достаточно файлов сохранено открытым, система может перестать работать при попытке открыть дополнительный файл.

Для большинства ресурсов, мы хотим обе из этих вещей. Мы хотим соглашение быть в состоянии сказать, что "мы сделаны с этим ресурсом теперь", и мы хотим удостовериться, что существует, по крайней мере, некоторый шанс для очистки для случая автоматически, если мы забываем делать это вручную. Это - то, где шаблон "IDisposable" играет роль. Это - соглашение, которое позволяет IDispose и финализатору играть приятно вместе. Вы видите, как шаблон работает путем рассмотрения официальная документация для IDisposable.

Нижняя строка: , Если то, что Вы действительно хотите сделать, должно просто удостовериться, что память освобождена, тогда IDisposable и финализаторы не помогут Вам. Но интерфейс IDisposable является частью чрезвычайно важного шаблона, который должны понять все программисты.NET.

101
ответ дан Curt Hagenlocher 26 November 2019 в 22:24
поделиться

@Curt Hagenlocher - это наоборот. Я понятия не имею, почему так многие проголосовали за него, когда это неправильно.

IDisposable для , справился ресурсы.

Финализаторы для неуправляемы ресурсы.

, пока Вы только используете управляемые ресурсы и @Jon Limjap и я, совершенно корректны.

Для классов, которые используют неуправляемые ресурсы (и принимают во внимание, что подавляющее большинство.Net классов не делает) ответ Patrik является всесторонней и лучшей практикой.

Избегают использования GC.Collect - это - медленный способ иметь дело с управляемыми ресурсами, и ничего не делает с неуправляемыми, если Вы правильно не создали свой ~Finalizers.

<час>

я удалил комментарий модератора из исходного вопроса в соответствии с https://stackoverflow.com/questions/14593/etiquette-for-modifying-posts

0
ответ дан Community 26 November 2019 в 22:24
поделиться

Konrad Rudolph - да, обычно финализатор не делает ничего вообще. Вы не должны реализовывать его, если Вы не имеете дело с неуправляемыми ресурсами.

Затем при реализации его Вы используете , Microsoft располагает шаблон (как уже описано)

  • public Dispose(), вызовы protected Dispose(true) - имеют дело и с управляемыми и с неуправляемыми ресурсами. Вызов Dispose() должен подавить завершение.

  • ~Finalize вызовы protected Dispose(false) - имеет дело с неуправляемыми ресурсами только. Это предотвращает неуправляемые утечки памяти, если Вам не удается звонить public Dispose()

~Finalize, является медленным, и не должен использоваться, если у Вас действительно нет неуправляемых ресурсов для контакта с.

Управляемые ресурсы не могут утечка памяти, они могут только потратить впустую ресурсы для текущего приложения и замедлить его сборку "мусора". Неуправляемые ресурсы могут просочиться, и ~Finalize лучшая практика, чтобы гарантировать, чтобы они не делали.

В любом случае using лучшая практика.

0
ответ дан Keith 26 November 2019 в 22:24
поделиться

@Keith:

IDisposable для управляемых ресурсов.

Финализаторы для неуправляемых ресурсов.

Жаль, но это просто неправильно. Обычно, финализатор не делает ничего вообще. Однако, если эти располагают шаблон , был правильно реализован, финализатор пытается вызвать Dispose.

Dispose имеет два задания:

  • Бесплатные неуправляемые ресурсы, и
  • бесплатные вложенные управляемые ресурсы.

И здесь Ваш оператор играет роль, потому что это верно, что при завершении, объект никогда не должен пробовать к бесплатным вложенным управляемым ресурсам, поскольку они, возможно, были уже освобождены. Это должно все еще освободить неуправляемые ресурсы все же.

однако, финализаторы не имеют никакого задания кроме звонить Dispose и сказать ему не касаться управляемых объектов. Dispose, когда названо вручную (или через Using), буду освобождать все неуправляемые ресурсы и передам эти Dispose сообщение к вложенным объектам (и методы базового класса), но это будет никогда свободный любая (управляемая) память.

0
ответ дан Konrad Rudolph 26 November 2019 в 22:24
поделиться

У Вас может быть детерминированное объектное разрушение в C++

, Вы никогда не хотите назвать GC.Collect, это смешивает с самонастраиваемым из сборщика "мусора", чтобы обнаружить давление памяти и в некоторых случаях ничего не сделать кроме увеличения текущее поколение каждого объекта на "куче".

Для тех, которые отправляют ответы IDisposable. Вызов Расположить метод не уничтожает объект как автора вопроса, описывает.

0
ответ дан Brian Leahy 26 November 2019 в 22:24
поделиться

Интерфейс IDisposable действительно для классов, которые содержат неуправляемые ресурсы. Если Ваш класс не содержит неуправляемые ресурсы, почему делают Вас потребность для освобождения ресурсов, прежде чем сборщик "мусора" сделает это? Иначе просто удостоверьтесь, что Ваш объект инстанцируют уже в возможном и выходит из объема как можно скорее.

0
ответ дан Tundey 26 November 2019 в 22:24
поделиться

Если Вы не хотите к (или не может) реализовывать IDisposable на Вашем классе, можно вызвать сборку "мусора" как это (но это медленно) -

GC.Collect();
0
ответ дан Seibar 26 November 2019 в 22:24
поделиться

Если MyClass реализует IDisposable, можно сделать просто это.

MyClass.Dispose();

Лучшая практика в C#:

using( MyClass x = new MyClass() ) {
    //do stuff
}

, Поскольку это оборачивает расположение в попытке наконец и удостоверяется, что никогда не пропускается.

0
ответ дан Keith 26 November 2019 в 22:24
поделиться

Извините, но выбранный ответ здесь является неправильным. Как несколько человек заявили, впоследствии Располагают, и реализующий IDisposable не имеет никакого отношения к освобождению памяти, связанной с классом.NET. Это главным образом и традиционно привыкло к бесплатным неуправляемым ресурсам, таким как дескрипторы файлов и т.д.

, В то время как Ваше приложение может назвать GC.Collect (), чтобы попытаться вызвать набор сборщиком "мусора", это будет только действительно иметь эффект на те объекты, которые являются на корректном уровне поколения в freachable очереди. Таким образом, возможно, что при очистке всех ссылок на объект это могли бы все еще быть несколько вызовов к GC.Collect (), прежде чем фактическая память будет освобождена.

Вы не говорите в своем вопросе, ПОЧЕМУ Вы чувствуете потребность сразу освободить память. Я понимаю, что иногда могут быть необычные обстоятельства, но серьезно, в управляемом коде почти всегда лучше позволить соглашению во время выполнения с управлением памятью.

, Вероятно, лучший совет, если Вы думаете свой код, израсходовал память, более быструю, чем GC освобождает его тогда, необходимо рассмотреть код, чтобы гарантировать, что ни на какие объекты, которые больше не необходимы, не ссылаются ни в каких структурах данных, у Вас есть ложь вокруг в статических участниках, И т.д. Также стараются избегать ситуаций, где у Вас есть круговые ссылки на объект, поскольку возможно, что они не могут быть освобождены также.

1
ответ дан Shaun Austin 26 November 2019 в 22:24
поделиться

@Keith,

я соглашаюсь со всеми Вашими правилами кроме № 4. Добавление финализатора должно только быть сделано при очень определенных обстоятельствах. Если класс использует неуправляемые ресурсы, те должны быть очищены в Вашем Располагать (bool) функцию. Эта та же функция должна только управляемые ресурсы очистки, когда bool верен. Добавление финализатора добавляет стоимость сложности для использования Вашего объекта как каждый раз, когда Вы создаете новый экземпляр, это должно также быть помещено в очередь завершения, которая проверяется каждый раз, когда GC выполняет цикл сбора. Эффективно, это означает, что Ваш объект переживает один цикл/поколение дольше, чем это должно так, финализатор может быть выполнен. Финализатор не должен считаться "системой поддержки".

GC только выполнит цикл сбора, когда он решит, что существует недостаточно доступной памяти в "куче" Gen0 для выполнения следующего выделения, если Вы не "помогаете" ему путем вызова GC.Collect () для принуждения внеполосного набора.

нижняя строка - то, что, неважно, что, только знает GC, как высвободить средства путем вызова Расположить метода (и возможно финализатор, если Вы реализованы). Это до того метода, чтобы "сделать правильную вещь" и очистить любые используемые неуправляемые ресурсы и дать любым другим управляемым ресурсам команду называть их Располагающего метод. Очень эффективно в том, что это делает и может самооптимизировать в большой степени, пока этому не помогают внеполосные циклы сбора. Однако за исключением вызова GC.Collect явно Вы не имеете никакого контроля, когда и в том, от каких объектов порядка избавятся и память освобождена.

1
ответ дан Scott Dorman 26 November 2019 в 22:24
поделиться

Вы не можете действительно вынудить GC очистить объект, когда Вы хотите, хотя существуют способы вынудить его работать, ничто не говорит, что это - уборка весь объект, который Вы хотите/ожидаете. Лучше звонить, располагают в выгоде попытки исключая, наконец располагают попытку конца (VB.NET rulz) путь. Но Расположите, для чистки системных ресурсов (память, дескрипторы, соединения дб, и т.д. выделенные объектом детерминированным способом. Расположите не делает (и не может) очищать память, используемую самим объектом, только, GC может сделать это.

2
ответ дан Booji Boy 26 November 2019 в 22:24
поделиться

Полное объяснение Joe Duffy на" Располагает, Завершение и управление ресурсами ":

Ранее в.NET время жизни Framework’s, финализаторы последовательно упоминались как деструкторы программистами C#. Поскольку мы становимся более умными со временем, мы пытаемся достигнуть соглашения с тем, которые эти Располагают метод, действительно более эквивалентно деструктору C++ (детерминированному) , в то время как финализатор является чем-то совершенно отдельным (недетерминированным) . То, что C# одолжил синтаксис деструктора C++ (т.е. ~T ()), конечно, имело отношение, по крайней мере, к немногому разработка этого неправильного употребления.

3
ответ дан jfs 26 November 2019 в 22:24
поделиться
public class MyClass : IDisposable
{
    public void Dispose()
    {
       // cleanup here
    }
}

тогда можно сделать что-то вроде этого

MyClass todispose = new MyClass();
todispose.Dispose(); // instance is disposed right here

или

using (MyClass instance = new MyClass())
{

}
// instance will be disposed right here as it goes out of scope
3
ответ дан Darren Kopp 26 November 2019 в 22:24
поделиться

Смотрите на этот статья

, Реализовывая Расположить шаблон, IDisposable, и/или финализатор абсолютно не имеет никакого отношения к тому, когда память исправлена; вместо этого, это имеет все, чтобы сделать с сообщением GC как для исправления той памяти. Когда Вы звоните, Располагают (), Вы никоим образом не взаимодействуете с GC.

GC будет только работать, когда он решит, что потребность к (названный давлением памяти) и затем (и только тогда) будет он освобождать память для неиспользуемых объектов и уплотнять пространство памяти.

Вы могли вызов GC.Collect (), но Вы действительно не были должны, если нет очень серьезное основание к (который является почти всегда "Никогда"). При принуждении внеполосного цикла сбора как это, Вы на самом деле заставляете GC делать больше работы и в конечном счете можете закончить тем, что повредили свою производительность приложений. На время цикла сбора GC Ваше приложение находится на самом деле в замороженном состоянии..., чем больше циклов GC, которые работают, тем больше Ваше приложение проводит замороженного времени.

существуют также некоторые собственные вызовы API Win32, которые можно сделать для освобождения рабочего набора, но даже тех нужно избежать, если нет очень серьезное основание сделать это.

целая предпосылка позади gargbage собралась, время выполнения - то, что Вы не должны волноваться (так же) о том, когда время выполнения выделяет/освобождает фактическую память; только необходимо волноваться о проверке, что объект знает, как вымыться после себя, когда спросили.

6
ответ дан prince 26 November 2019 в 22:24
поделиться

Было бы уместно также упомянуть, что располагают, не всегда относится к памяти? Я располагаю ресурсы такие ссылки на файлы чаще, чем память. GC.Collect () непосредственно касается сборщика "мусора" CLR, и можете, или не может свободная память (в Диспетчере задач). Это, вероятно, повлияет на Ваше приложение отрицательными способами (например, производительность).

В конце дня, почему Вы хотите память назад сразу? Если будет давление памяти откуда-либо, то ОС получит Вас память в большинстве случаев.

14
ответ дан Brian Lyttle 26 November 2019 в 22:24
поделиться

Ответы на этот вопрос больше, чем немного перепутали.

заголовок спрашивает о распоряжении, но тогда говорит, что они хотят память назад сразу.

.Net , справился , что означает, что, когда Вы пишете.Net приложения, Вы не должны волноваться о памяти непосредственно, стоимость - то, что Вы не имеете прямого контроля над памятью также.

.Net решает, когда лучше мыться и свободная память, не Вы как.Net кодер.

Эти Dispose способ сказать.Net, что Вы сделаны с чем-то, но он на самом деле не освободит память, пока это не будет наилучшее время, чтобы сделать так.

В основном.Net на самом деле соберет память назад, когда для него будет самым легким сделать так - это очень хорошо в решении когда. Если Вы не пишете что-то очень интенсивно использующее память, Вы обычно не должны отвергать его (это - часть причины, которая игры не часто пишутся в.Net все же - им нужен полный контроль)

В.Net, который можно использовать GC.Collect() для принуждения его к сразу, но это - почти всегда плохая практика. Если.Net еще не очистил его, который означает, что это не особенно хорошее время для него, чтобы сделать так.

GC.Collect() берет объекты, которые.Net определяет, как покончено. Если Вы не расположили объект, которому нужен он.Net может решить сохранить тот объект. Это означает, что GC.Collect() является только эффективным, если Вы правильно реализуете свои доступные экземпляры.

GC.Collect() не замена для того, чтобы правильно использовать IDisposable.

Так Располагают, и память непосредственно не связаны, но они не должны быть. Правильно расположение будет делать Ваши.Net приложения более эффективными и поэтому использовать меньше памяти все же.

<час>

99% времени в.Net следующее является лучшей практикой:

Правило 1: , Если Вы ни с чем не имеете дело неуправляемый или это реализует IDisposable, тогда не волнуются о, Располагают.

Правило 2: , Если у Вас есть локальная переменная, которая реализует IDisposable, удостоверяются, что Вы избавляетесь от него в текущей области:

//using is best practice
using( SqlConnection con = new SqlConnection("my con str" ) )
{
    //do stuff
} 

//this is what 'using' actually compiles to:
SqlConnection con = new SqlConnection("my con str" ) ;
try
{
    //do stuff
}
finally
{
    con.Dispose();
}

Правило 3: , Если класс имеет свойство или членскую переменную, которая реализует IDisposable тогда, что класс должен реализовать IDisposable также. В том классе Располагают метод, можно также избавиться свойств IDisposable:

//rather basic example
public sealed MyClass :
   IDisposable
{   
    //this connection is disposable
    public SqlConnection MyConnection { get; set; }

    //make sure this gets rid of it too
    public Dispose() 
    {
        //if we still have a connection dispose it
        if( MyConnection != null )
            MyConnection.Dispose();

        //note that the connection might have already been disposed
        //always write disposals so that they can be called again
    }
}

Это не действительно завершено, который является, почему пример изолируется. Наследующие классы, возможно, должны наблюдать следующее правило...

Правило 4: , Если класс использует неуправляемый , ресурс тогда реализует IDispose , и добавляют финализатор.

.Net ничего не может сделать с неуправляемый ресурс, поэтому теперь мы говорим о памяти. Если Вы не чистите его, можно получить утечку памяти.

Расположить метод должен иметь дело и с [1 115], справился и неуправляемый ресурсы.

финализатор является предохранительной защелкой - он гарантирует, что, если кто-то еще создает и экземпляр Вашего класса и не удается расположить его 'опасное' неуправляемый , ресурсы могут все еще быть очищены.Net.

~MyClass()
{
    //calls a protected method 
    //the false tells this method
    //not to bother with managed
    //resources
    this.Dispose(false);
}

public void Dispose()
{
    //calls the same method
    //passed true to tell it to
    //clean up managed and unmanaged 
    this.Dispose(true);

    //as dispose has been correctly
    //called we don't need the 

    //'backup' finaliser
    GC.SuppressFinalize(this);
}

Наконец эта перегрузка Располагает, который берет булев флаг:

protected virtual void Dispose(bool disposing)
{
    //check this hasn't been called already
    //remember that Dispose can be called again
    if (!disposed)
    {
        //this is passed true in the regular Dispose
        if (disposing)
        {
            // Dispose managed resources here.
        }

        //both regular Dispose and the finaliser
        //will hit this code
        // Dispose unmanaged resources here.
    }

    disposed = true;
}

Примечание, что, как только это - все на месте другой управляемый код, создающий экземпляр Вашего класса, может просто рассматривать его как любой другой IDisposable (Правила 2 и 3).

19
ответ дан Keith 26 November 2019 в 22:24
поделиться

Можно только расположить экземпляры, которые реализуют интерфейс IDisposable.

Для принуждения мусора сразу собирают к свободному (неуправляемую) память:

GC.Collect();  
GC.WaitForPendingFinalizers();

Это обычно - плохая практика, но существует, например, ошибка в x64-версии платформы.NET, которая заставляет GC вести себя странный в некоторых сценариях, и затем Вы могли бы хотеть сделать это. Я не знаю, была ли ошибка разрешена уже. Кто-либо знает?

Для расположения класса Вы делаете это:

instance.Dispose();

или как это:

using(MyClass instance = new MyClass())
{
    // Your cool code.
}

, который переведет во время компиляции в:

MyClass instance = null;    

try
{
    instance = new MyClass();        
    // Your cool code.
}
finally
{
    if(instance != null)
        instance.Dispose();
}

можно реализовать интерфейс IDisposable как это:

public class MyClass : IDisposable
{
    private bool disposed;

    /// <summary>
    /// Construction
    /// </summary>
    public MyClass()
    {
    }

    /// <summary>
    /// Destructor
    /// </summary>
    ~MyClass()
    {
        this.Dispose(false);
    }

    /// <summary>
    /// The dispose method that implements IDisposable.
    /// </summary>
    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// The virtual dispose method that allows
    /// classes inherithed from this one to dispose their resources.
    /// </summary>
    /// <param name="disposing"></param>
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Dispose managed resources here.
            }

            // Dispose unmanaged resources here.
        }

        disposed = true;
    }
}
22
ответ дан Keith 26 November 2019 в 22:24
поделиться

Эта статья имеет довольно простую пошаговую демонстрацию. Однако наличие для вызова GC вместо того, чтобы позволить это взять его естественный курс обычно является знак плохого дизайна/управления памятью, особенно , если никакие ограниченные ресурсы не используются (соединения, дескрипторы, что-либо еще, что обычно приводит к реализации IDisposable).

, Что заставляет Вас должны делать это?

1
ответ дан Greg Hurlman 26 November 2019 в 22:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: