C# → Конструкторы и деструторы

Для простых типов (по значению) С# поддерживает два способа инициализации:

  • если переменная является локальной для метода или out-параметром метода (не инициализирована начальным значением, ссылка), то компилятор будет настаивать, чтобы в коде явно устанавливалось значение переменной до того, как она будет использована;
  • во всех остальных ситуациях (включая статические поля-члены и поля экземпляров) компилятор инициализирует переменные после их создания значениями по умолчанию.

Если указать начальное значение переменной (поля) при ее объявлении (intx = 10), то это значение будет всегда использоваться для инициализации.

Для класса можно написать статический конструктор без параметров который будет исполнен всего одни раз. Выполняется он при создании объектов одного класса (может понадобиться для инициализации статических переменных). Статический конструктор не имеет можификатора доступа, он никогда не вызывается C#, а только самой .NET при загрузке класса и может осуществлять доступ только к статическим полям класса.

    public class Authenticator
    {
        static Authenticator()
        {
            // задаём минимальную длиняу пароля
            minPasswordLength = 6;
        }

        private static readonly byte minPasswordLength;
    }

Константыне величины (const) являются неявно статическими. Величина является постоянной по определению, поэтому нет необходимости хранить ее копии для каждого экземпляра класса. На них всегда можно ссылаться через имя класса:

int x = Authenticator.MaxLength;//конс.

Синтаксически не корректно объявлять величины const статическими (static)!

Ключевое слово readonly допускает, что поле будет константным, но для определения его начального значения необходимо выполнить некоторые вычисления. Присвоить значение полю readonly можно только внутри конструктора(!). Поле readonly может быть полем экземпляра, а не статическим полем и иметь различные значения для каждого экземпляра класса. Это означает, что для того, чтобы поле было статическим его необходимо явно объявить таким.

Если не инициализировать поле readonly в конструкторе, то оно будет иметь значению по умолчанию для данного типа или то значение, которое было присвоено ему при объявлении.

Вызов конструктора из других конструкторов

      public class Authenticator
      {
        // сначала вызыв. другой конструктор
        public Authenticator() : this("none") 
        {
            // что то делаем
        }

        public Authenticator(string initialPassword)
        {
            password = initialPassword;
        }

        private string password;
    }

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

Ключевые слова base и this являются единственными допустимыми ключевыми словами, которые можно указывать в строке вызова другого конструктора. Все остальное сгенерирует ошибку компиляции. Замечу также, что может быть указан только один конструктор.

Конструкторы производных классов

     public GenericCustomer(string initName) 
     {
         name = initName;
     }

      public class PayAsYouGoCustomer : GenericCustomer
      {
        // конструктор без параметров в базовом классе
        // отсутствует поэтому необходимо вызивать собственный
        public PayAsYouGoCustomer(string initName) : base(initName) 
        {
           // ..
        }
      ...

    Nevermore60Customer Alex = new Nevermore60Customer("Alex");

Теперь конструктор будет создаваться только в том случае, если в конструктор будет передаваться строка, содержащая имя пользователя.

Деструкторы Finalize()

Finalize() наиболее близко соответствует концепции традиционного деструктора. Если объявить в классе метод Finalize() он будет автоматически вызываться при уничтожении экземпляра класса.

Finalize() является детерминированным, т.е. нет способа выяснить, когда будет вызван сборщик мусора и соответственно Finalize(). Следовательно, в метод Finalize() нельзя помещать код, который должен выполняться в какое-то определенное время. Запустить сборщик мусора можно с помощью метода System.GC.Collect().

Не рекомендуется реализовывать метод Finalize() если только класс действительно не нуждается в нем. Это наносит сильный удар по производительности при сборке мусора.

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

Реализация:

  ~MyClass () 
  { 
     //.. 
  }

Деструкторы Dispose() и Close()

Они работают таким образом, что при желании вы можете определить один из них для класса, понимая при этом, что клиентский код обязан явно вызывать этот метод для освобождения ресурсов. Ресурсы освобождаются сразу после того, как отпадает надобность в них. Недостаток: вы полагаетесь на то, что клиентский код будет вести себя корректно и вызовет этот метод (однако это может и не произойти).

Типичное решение – использование Dispose() и Close() совместно с Finalize():

      public class myClass : MasterClass
      {
        private int x;
        public void Dispose()
        {
            // освобождаем ресурсы
            //...
            GC.SuppressFinalize(this); 
            // для объекта (this) не 
            // нужно больше вызивать Finalize
        }

        protected override void Finalize()
        {
            // освобождаем ресурсы
            base.Finalize();
        }
    }

В приведенном примере: Если клиентский код не забудет вызвать Dispose(), ресурсы будут освобождены вовремя. Если же забудет, то Finalize() будет вызван при сборке мусора. Метод GC.SuppressFinalize() информирует среду исполнения о том, что для объекта переданного в качестве параметра не нужно больше вызывать Finalize().

Разница между Close() и Dispose() состоит главным образом в соглашении о их применению. Close() предполагает, что ресурс может быть позже открыт, в то время как вызов Dispose() означает, что клиент закончил работу с этим ресурсом навсегда. Можно реализовать оба метода.

C# предлагает синтаксис, который можно использовать для гарантии того, что Dispose (но не Close() (!) будет вызван для объекта автоматически, и его не нужно вызывать вручную, когда ссылка на него выйдет из области видимости (using):

конструктор C#

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

Лучшая альтернатива определить класс унаследованным от интерфейса IDisposable:

    public class RessourceG : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("Resource Dispose!");
        }
    }

Наследование от IDisposable вынуждает производный класс реализовать метод Dispose(), если этого не будет сделано, возникает ошибка при компиляции. Выигрыш – компилятор может убедиться, что объект определенный в выражении using имеет метод Dispose(), который он может вызвать автоматически.Related: puente de los tomates matamoros horarios, acro police certificate tracking, don braid mainfreight net worth, croydon parking fines appeal, richmond, il police blotter, san juan college class schedule, chopped judges salary, best rock hunting in upper peninsula, rabino pinerolo auto usate, ed norris net worth, which members of the band are still alive, our lady of lourdes catholic church mass schedule, dill pickle lemonade recipe, imagenes provocativas de pareja con frases, colorado fingerprinting locations,