140 likes | 472 Views
Жизненный цикл объекта. Создание объекта при вызове оператора new Под объект выделяется область памяти из управляемой кучи . Область памяти инициализируется при работе конструктора. Возможно захватывается ресурс, например, открывается файл или устанавливается соединение с базой данных.
E N D
Жизненный цикл объекта • Создание объекта при вызове оператора new • Под объект выделяется область памяти из управляемой кучи. • Область памяти инициализируется при работе конструктора. • Возможно захватывается ресурс, например, открывается файл или устанавливается соединение с базой данных. • Использование объекта • Вызываются методы объекта, производится доступ к полям данных объекта. • Уничтожение объекта (точное время неопределено) • При помощи деструктора (финализатора) объект превращается в область памяти. • Область памяти возвращается системе. • Освобождением занятых ресурсов занимается сборщик мусора.
Деструктор • В классе можно определить деструктор. • В отличие от C++ порядок вызова деструкторов в C# неопределен. Перед освобождением памяти сборщик мусора вызывает деструктор, но возможны ситуации, когда деструктор для объекта не вызывается совсем. • Определять свои деструкторы нужно только в случае крайней необходимости - они создают значительную нагрузку на систему. • На самом деле наличие в классе деструктора означает неявное переопределение метода Finalize class T { ~T() { Console.WriteLine(“T destructed”); } } class T { protected override void Finalize(){ try {Console.WriteLine(“T destructed”);} finally { base.Finalize();} } }
Сборщик мусора ( Garbage Collector) • CLR использует модель сборки с поколениями 0 – (128-256-512 K) – динамически настраивается 1 – (2Mб) 2 – (10 Mб) • Сборщик мусора начинает работу, когда заполнено поколение 0, неиспользуемые объекты освобождаются, а все остальные перемещаются в поколение 1. • Для больших объектов (> 85000 байт) своя куча и свой алгоритм работы GC. Массивные объекты сборщик мусора не перемещает. • Алгоритмы сборки отличаются в debug и release версиях и в различных версиях OC. Информация: 1. Рихтер Дж. CLR via C#. Программирование на платформе Microsoft .NET Framework 2.0 на языке C#. -Изд. Microsoft Press. Русская редакция, 2007. 2. МаониСтивенс (MaoniStephens).Представляем кучу для массивных объектов - MsDN Magazine ,июнь 2008.
Сборка мусора для объектов с завершением • Перед вызовом Ctor объекты с завершением (с Dtor)заносятся в специальный список объектов, для которых надо вызвать Dtor перед освобождением памяти. • При сборке мусора в поколении 0 объекты с завершением не уничтожаются, а заносятся в специальную очередь завершения. Очередь завершения обрабатывает специальный высокоприоритетный поток. В каком случае Dtor может бытьне выполнен? • После завершения работы приложения CLR вызывает Finalize() для каждого объекта с завершением, но если время возврата из него более 2 сек, CLR завершает процесс и остальные методы Finalize() не вызываются.
Исключения • В коде, использующем библиотеки классов, обработка ошибок во время выполнения программы должна быть разделена на две части : • генерация сообщения об ошибке, которая не может быть обработана локально; • обработка ошибки в том месте, где достаточно информации для анализа нестандартной ситуации и ее обработки. • Механизм исключений C# дает возможность писать устойчивый и простой в сопровождении код. • Можно передать произвольный объем информации в точку обработки ошибки.
Исключенияв C# и C++ • Механизм исключений в C# почти полностью совпадает с механизмом исключений в C++. Отличия: • все исключения C# должны быть экземплярами классов, производных от класса System.Exception; • в C# можно использовать блок finally, который выполняется в любом случае, независимо от того, брошено исключение или нет; • в C# для системных исключений (переполнение, деление на нуль или нулевая ссылка) также определены классы, которые обрабатываются наравне с исключениями уровня приложения. • Исключение явно порождается выражением throw throw new FileNotFoundException(“test.dat”);
Тип System.Exception • Все исключения должны иметь тип System.Exception или быть его потомками publicclassException : ISerializable { … publicException(); publicException( stringmessage ); publicException( stringmessage, ExceptioninnerException ); publicvirtualstringMessage {get;} publicExceptionInnerException {get;} // предыдущее исключение, // если данное было сгенерировано при // обработке предыдущего. public virtual string StackTrace { get;} // строка с именами // и сигнатурами последовательных вызовов, // которые привели к генерации исключения. }
Иерархия классов-исключений ( часть классов) System.ObjectSystem.ExceptionSystem.SystemExceptionSystem.ArgumentExceptionSystem.ArithmeticExceptionSystem.ArrayTypeMismatchExceptionSystem.BadImageFormatExceptionSystem.FormatExceptionSystem.IndexOutOfRangeExceptionSystem.InvalidCastExceptionSystem.NullReferenceException System.OutOfMemoryException System.ExecutionEngineException System.StackOverflowException ... System.ObjectSystem.ExceptionSystem.SystemExceptionSystem.IO.IOExceptionSystem.IO.DirectoryNotFoundExceptionSystem.IO.EndOfStreamExceptionSystem.IO.FileLoadExceptionSystem.IO.FileNotFoundExceptionSystem.IO.PathTooLongException
Блок finally • Выполняется в любом случае, независимо от того, брошено исключение или нет. • Если нет исключения, выполняются все операторы в блоке try, а затем операторы блока finally. • Если брошено исключение, CLR просматривает стек вызовов в поиске обработчика с нужным типом фильтра, и выполняет • сначалаблок finally в тех методах, где нетобработчика с требуемым фильтром • затем блок catch • затем finally из блока try с обработчиком • Допустимые конфигурации • try – catch –finally • try – catch • try – finally
Порядок обработки исключений static void Main ( string[] args) {… код C# … Abc abc = new Abc(); try { abc.Method1(); … код C# … 1 } сatch(Exception1 ex) { … 1 обработка исключений класса … Exception1 и его потомков } catch (Exception2 ex) { … 2 обработка исключений класса … Exception2 и его потомков } finally { … 1 … } } partial class Abc { public void Method1() { … код C# try { … код C# … 2 Method2(); … код C# … 3 } catch (Exception3 ex) { … 3 обработка исключений класса … Exception3 и его потомков } finally { … 2 …} … код C# … 4 } partial class Abc { public void Method2() { … код C# try { … код C# … 5 if( < условие>) throw new ExceptionN(); … код C# … 6 } сatch(Exception1 ex) { … 4 обработка исключений класса … Exception1 и его потомков } catch (Exception4 ex) { … 5 обработка исключений класса … Exception4 и его потомков } finally { … 3 … } … код C# … 7 } <условие>== false код 2 код 5 код 6 finally3 код 7 код 3finally 2 код 4 код 1 finally1 <условие>== true throw Exception1 код 2 код 5 catch4 finally3 код 7 код 3finally 2 код 4 код 1 finally1 <условие>== true throw Exception3 код 2 код 5 finally3 catch 3finally 2 код 4 код 1 finally1 <условие>== true throw Exception2 код 2 код 5 finally3 finally 2 catch2 finally1
Задача освобожденияресурсов. Решение в C++ void main () { try { ... код С++ f(); ... код С++ } catch (exception ex) { ... код С++ } } void f() { Resource R (); // R.Lock(); Lock_Resource LR(R); fInner(R); // R.Unlock(); } void fInner (Resource& rc) { ... код бросает исключение } class Resource { public: void Lock() { ... захват ресурса} void Unlock() { ... освобождение ресурса} Resource () {...} private: ... данные }; class Lock_Resource { public: Lock_Resource (Resource &rci) { rc = rci; rc.Lock();} ~Lock_Resource() { rc.Unlock();} private: Resource& rc; };
Задача освобожденияресурсов. Решение в C#. public static void Main ( string[] args) { try { ... код С# f(); ... код С# } catch (exception ex) { ... код С# } } public void f() { Resource R (); R.Lock(); try { fInner(R);} finally { R.Unlock();} } void fInner (Resource& rc) { ... код бросает исключение } class Resource { public void Lock() { ... захват ресурса} public void Unlock() { ... освобождение ресурса} public Resource () {...} private: ... данные }
Типы с явным освобождением ресурсов • В типах, которые поддерживают модель детерминированного освобождения ресурсов, следует реализовать метод void Dispose(); в котором размещают код, освобождающий ресурсы. • Оператор using - краткая форма try-finally class A : IDisposable { } class B : IDisposable { } using(a = new A()) using(b = new B()) { // … } a = new A(); try { b = new B(); try { … } finally { b.Dispose(); } } finally { a.Dispose(); }
Пример реализации метода Dispose() public class MyResource: IDisposable { private IntPtr handle; // unmanaged resource private Component component = new Component(); // managed resource private bool disposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { // disposing == true явный вызов из Dispose() // disposing == false вызов из деструктора if ( !this.disposed ) { if ( disposing ) // явный вызов Dispose() {component.Dispose(); // Dispose managed resources. } CloseHandle(handle);// Clean up unmanaged resources } disposed = true; } ~MyResource() { Dispose(false); } }