Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: C# две формы и одна коллекция  (Прочитано 32898 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Сергей
Интересующийся

ua
Offline Offline

« : 13-02-2011 19:15 » 

Помогите, пожалуйста, разобраться в следующей проблеме. Пример создан специально, чтобы показать проблему. В проекте имеем основную форму(Form1) на которой две кнопки одна добавляет элемент в коллекцию(public List<string> spok) которая объявляется в классе Class1, вторая кнопка вызывает форму(Form2). На второй форме имеется кнопка для добавления элемента в коллекцию(public List<string> spok) которая объявляется в классе Class1. Проблема в том что во второй форме элемент добавляется в новую свою колекцию, а нужно чтобы продолжала добавлять в первую.
Form1
Код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Primer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Form2 f = new Form2();
        Class1 g = new Class1();
        private void button1_Click(object sender, EventArgs e)
        {
            g.ZaPis("a");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            f.Show();
        }
    }
}
Form2
Код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Primer
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
        Class1 h = new Class1();
        private void button1_Click(object sender, EventArgs e)
        {
            h.ZaPis("b");
        }
    }
}
Class1
Код:
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Primer
{
    class Class1
    {
        public List<string> spok = new List<string>();
        public void ZaPis(string q)
        {
            MessageBox.Show(spok.Count + "");
            spok.Add(q);
        }
    }
}
Если скомпилировать пример при нажатии на кнопку в первой форме будет видно, как увеличивается размер коллекции, а во второй форме всё начинается с нуля.
Записан
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 13-02-2011 19:21 » 

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

Это вовсе не проблема. Программа работает именно так, как написана. В обеих формах создается собственный экземпляр Class1, и каждая форма работает со своим.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 13-02-2011 19:26 » 

Грубым частным решением является передача второй форме (коль скоро за её показ отвечает первая форма) ссылки на исходную коллекцию, создаваемую первой формой. В конструктор, например. (Что, наверное, также покажет, что инициализация членов класса Form1 вне конструктора не обязательно является удачной идеей.)

Более общим решением является так называемая архитектура Model-View-Controller и её варианты. Так или иначе, суть в разделении модели данных и способов обеспечить пользователю представление этой модели и механизмы её изменения. Например, в случае, если коллекция строго одна на всю программу (а похоже, задача именно такова), паттерн Одиночка (Singleton) здесь помог бы при работе с одной и той же коллекцией "отовсюду".
Записан
ezus
Опытный

il
Offline Offline

« Ответ #3 : 14-02-2011 16:46 » 

Есть еще одно не очень красивое решение - объявить spok как static.
Записан
Сергей
Интересующийся

ua
Offline Offline

« Ответ #4 : 14-02-2011 17:51 » 

В принципе объявить spok как static
Код:
static List<string> spok = new List<string>();
решает данную проблему, но смущает
Цитата
Есть еще одно не очень красивое решение
хотелось бы знать, почему оно не красивое?

И хотелось бы поподробнее узнать о паттерн Одиночка (Singleton), я поискал и нашёл общий шаблон, но с какой стороны его приткнуть пока не пойму.
Код:
class Earth 
    {
      private static Earth instance;
       //конструктор объявлен так, чтобы не исключать наследование
      protected Earth()
      {
      }
      public static Earth Instance()
      {
         //используем «ленивую» инициализацию
        if (instance == null)
        {
            instance = new Earth();
        }
        return instance;
     }
}
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 14-02-2011 18:13 » 

Сергей, решение со static некрасивое, потому что это полумера: фактически, это тот же паттерн "одиночка", но плоховато инкапсулированный, из-за чего решение выглядит кривовато: получается, Class1 порождает экземпляры, которые ничего другого не делают, кроме как обслуживают статический член этого класса (коллекцию). Смысл в порождении объектов теряется, код становится мутным (хотя, уже сам факт наличия класса с именем Class1 делает код мутным - из названия совершенно неясно, что этот класс собой представляет).

Приведённый тобой пример тоже неидеален, но, по крайней мере, понятно, что такое Earth и почему оно не даёт создавать отдельную Землю на каждый чих, а заставляет запрашивать уже существующий экземпляр. Заменить Earth на Data (шире - Model) - получается "одиночка" для единственной существующей в программе модели данных, которую можно дёргать из любой формы, она всегда будет в единственном экземпляре.
« Последнее редактирование: 14-02-2011 18:19 от Вад » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #6 : 14-02-2011 19:09 » 

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

Можно использовать h в качестве буфера, и по закрытии Form2 перебросить объекты из h в g.

Более простым и оптимальным будет передать ссылку на g в Form2, дополнив её соответствующим конструктором, как предложил Вад.

        Class1 g = new Class1();
        Form2 f = new Form2(g);

и работать в Form2 с g.

Хотя я, честно говоря, не совсем понимаю "грубости" данного решения. Форма2 предназначена для заполнения коллекции, которую она получает в качестве параметра.
« Последнее редактирование: 14-02-2011 19:11 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Сергей
Интересующийся

ua
Offline Offline

« Ответ #7 : 14-02-2011 19:40 » 

Да в принципе вариантов решения как оказалось множество. Я так думаю, грубые решения ведь тоже не зря существуют, хотя бы те самые паттерны. Кстати посмотрите, правильно я написал код с паттерном:
Код:
namespace Primer
{
    class Class1
    {
        //static List<string> spok = new List<string>();
        Earth y = Earth.Instance();
        public void ZaPis(string q)
        {
            MessageBox.Show(y.spok.Count + "");
            y.spok.Add(q);
        }
    }
    class Earth
    {
        private static Earth instance;
        public List<string> spok = new List<string>();
        //конструктор объявлен так, чтобы не исключать наследование
        protected Earth()
        {
           
        }
        public static Earth Instance()
        {
            //используем «ленивую» инициализацию
            if (instance == null)
            {
                instance = new Earth();
            }
            return instance;
        }
    }
}
Записан
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 14-02-2011 20:46 » 

Я так думаю, грубые решения ведь тоже не зря существуют, хотя бы те самые паттерны.

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

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 14-02-2011 21:41 » 

Сергей, в последнем решении, если есть, кхм, Earth, то зачем нужен Class1? Улыбаюсь
Записан
Сергей
Интересующийся

ua
Offline Offline

« Ответ #10 : 15-02-2011 00:30 » 

Вад, отвечаю на Ваш вопрос:
программа Primer специально создана, чтобы показать проблему без лишнего кода, на самом деле основная программа больше. В отдельном классе создается коллекция, видимая для всей программы и в единственном экземпляре. В классе Class1 происходит запись – чтение в файл. В Form2 добавляется информация, в других классах обрабатывается и т.д. в принципе как того требует ООП. Это будет моя первая нормальная программа, вдруг что-то не так спорить не буду.

А теперь что помогло, а с чем добавилось проблем:
С паттерном и static в этой программе нормально, а с передачей ссылки на g в Form2 может и красиво, но не совсем хорошо. Принимает g метод Form2() и инкапсулирует внутри себя, а для остального класса g невидим, в том числе и для обработчиков событий.
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 15-02-2011 06:22 » 

Вад, отвечаю на Ваш вопрос:
В классе Class1 происходит запись – чтение в файл. В Form2 добавляется информация, в других классах обрабатывается и т.д. в принципе как-того требует ООП. Это будет моя первая нормальная программа, вдруг что-то не так спорить не буду.
Ага, вот поэтому я и говорил об архитектуре Model-View-Controller (Модель-Представление-Поведение) и её вариациях: если есть данные, которые из разных мест программы запрашиваются для отображения, обновляются и сбрасываются на диск при каких-то условиях (или при каждом изменении?), логично спрятать от всех этих Form1 и Form2 нюансы, связанные с внутренней логикой устройства модели и работы контроллера (читай: то, какая коллекция там используется, а также каким именно образом происходит её модификация и какие побочные действия происходят), оставив только более высокоуровневый интерфейс. Хотя бы для того, чтобы все абстракции были на своих местах. Впрочем, тут главное не увлечься Улыбаюсь Я бы развил эту мысль дальше, но пока опасаюсь, насколько это всё понятно.

В приведённом коде была слабая попытка это сделать (введением метода zapis у класса Class1), но она не избавляет от возможности злоупотребить доступом к коллекции и вносить изменения напрямую, минуя упомянутый метод и ломая логику работы программы.

Цитата
С паттерном и static в этой программе нормально, а с передачей ссылки на g в Form2 может и красиво, но не совсем хорошо. Принимает g метод Form2() и инкапсулирует внутри себя, а для остального класса g невидим, в том числе и для обработчиков событий.
Разумеется, нужно не просто принимать в конструктор в качестве аргумента ссылку на g, но ещё и сохранять эту ссылку в виде члена класса:
Код: (Text)
public partial class Form2 : Form
    {
        public Form2(Class1 data)
        {
            h = data; // <<--- внимание сюда
        }
        Class1 h = null;
        private void button1_Click(object sender, EventArgs e)
        {
            h.ZaPis("b");
        }
    }
« Последнее редактирование: 15-02-2011 07:07 от Вад » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 15-02-2011 06:54 » 

Цитата: Сергей
В Form2 добавляется информация, в других классах обрабатывается и т.д. в принципе как того требует ООП.
Это где ООП требует в одном классе добавлять информацию, а в других классах обрабатывать?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Сергей
Интересующийся

ua
Offline Offline

« Ответ #13 : 15-02-2011 18:21 » 

Хотел немного поспорить, но пока соглашусь, что не всё понятно. Может у кого-то есть ссылки на литературу или сайты.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 15-02-2011 19:51 » 

Сергей, поспорить о чём? Соглашаешься с чем? Литература и сайты на какую тему, по какому вопросу?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Сергей
Интересующийся

ua
Offline Offline

« Ответ #15 : 15-02-2011 20:10 » 

Литература по программированию.
С передачей ссылки проблема остается.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 15-02-2011 20:15 » 

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

Цитата: Сергей
Литература по программированию.
Непонятно. С азов что ли?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 15-02-2011 21:08 » 

С передачей ссылки проблема остается.
Сергей, похоже, ты не любишь пользоваться конструкторами. Отчего так?
Сергей, я же приводил рабочий код с конструктором и заранее предупреждал о той проблеме, которую ты показываешь.
« Последнее редактирование: 15-02-2011 21:11 от Вад » Записан
Сергей
Интересующийся

ua
Offline Offline

« Ответ #18 : 16-02-2011 16:56 » 

Честно сказать даже не знаю, причём здесь конструктор, наша задача передать объект по ссылке, что практически не возможно компилятор находит всё новые и новые ошибки то поле не статическое, то уровень доступа. Самое большее, что я смог передать по ссылке это переменную. В принципе я решил свою проблему, но хотелось бы довести до работоспособности самый красивый вариант.
Сергей, похоже, ты не любишь пользоваться конструкторами. Отчего так?
А по конструкторам тоже полезная вещь для конструирования типов, правда, зачем конструировать переменные даже не знаю. Скорее всего, это приходит с опытом во время решения определённых задач.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 16-02-2011 21:07 » 

Цитата: Сергей
А по конструкторам тоже полезная вещь для конструирования типов, правда, зачем конструировать переменные даже не знаю.
Это очень загадочная фраза.

Конструирование типов производит программист во время написания кода и компилятор во время компиляции. Конструктор как процедура производит конструирование объекта во время исполнения.

Объект - это не переменная, это её содержимое.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #20 : 16-02-2011 21:18 » 

Димка, а вот это ты понял?

наша задача передать объект по ссылке, что практически не возможно компилятор находит всё новые и новые ошибки то поле не статическое, то уровень доступа. Самое большее, что я смог передать по ссылке это переменную.

Я - нет. Раз пять прочитал. Получается объкт передать нельзя, а переменную можно?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 16-02-2011 21:32 » 

Димка, а вот это ты понял?

наша задача передать объект по ссылке, что практически не возможно компилятор находит всё новые и новые ошибки то поле не статическое, то уровень доступа. Самое большее, что я смог передать по ссылке это переменную.

Я - нет. Раз пять прочитал. Получается объкт передать нельзя, а переменную можно?

Я понял. Понял, что от приведённой выше версии с некорректной инициализацией полей при их объявлении Сергей развивает решение методом тыка, и этот метод рабочих решений не порождает.
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 16-02-2011 21:39 » 

Сергей, ты приведённый мной в 11-м комменте код смотрел? Там приводится типичный пример "нестандартной" инициализации поля класса: нестандартной в том смысле, что в том конкретном случае требуется не создать пустой список с помощью штатного конструктора (  List() ), а скопировать ссылку на уже имеющийся где-то список, то этот имеющийся список идёт параметром конструктора списка, и само действие по присваиванию происходит там же - потому что только в этот момент объект получает эту саму ссылку, которую нужно скопировать. Надеюсь, я не слишком сложно объясняю?

В целом же, считаю, что коль скоро C# является в определённой степени объектно ориентированным языком и навязывает соответствующий подход при программировании, неплохо бы изучить базовые понятия - что такое объект и его конструирование. И забыть пока про вычитанный где-то java-стиль инициализации полей класса, если ты не понимаешь, что и в какой момент при этом происходит.
« Последнее редактирование: 16-02-2011 21:41 от Вад » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #23 : 16-02-2011 21:50 » 

Вад, мне кажется у него хроническое непонимание понятий "объект" и "переменная".
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Сергей
Интересующийся

ua
Offline Offline

« Ответ #24 : 16-02-2011 22:16 » 

Вад, я всё прочитал и попробовал практически, теоретически я понимаю, а вот практически выполнить не могу.
Я - нет. Раз пять прочитал. Получается объкт передать нельзя, а переменную можно?
Передаем переменную
Код:
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Class1 g = new Class1();
        static int e = 2;
        Form2 f = new Form2(e);
        private void button1_Click(object sender, EventArgs e)
        {
            g.ZaPis("a");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            f.Show();
        }
    }
public partial class Form2 : Form
    {
        public Form2(int data)
        {
            InitializeComponent();
            t = data;
        }
        int t;
        static Class1 g = new Class1();
        private void button1_Click(object sender, EventArgs e)
        {
            g.ZaPis("b");
        }
    }
Передаем объект
Код:
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Class1 g = new Class1();
        static int e = 2;
        Form2 f = new Form2(g);
        private void button1_Click(object sender, EventArgs e)
        {
            g.ZaPis("a");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            f.Show();
        }
    }
    public partial class Form2 : Form
    {
        public Form2(Class1 data)
        {
            InitializeComponent();
            t = data;
        }
        Class1 t;
        //static Class1 g = new Class1();
        private void button1_Click(object sender, EventArgs e)
        {
            t.ZaPis("b");
        }
    }
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 16-02-2011 23:09 » 

Сергей, просто поверь на слово, что ты сейчас занимаешься ерундой Улыбаюсь К сожалению, не могу посоветовать хорошего учебника на C#, подробно разбирающего, что здесь происходит. Если вкратце, все три выделенные строчки в следующем коде равноправны:
Код: (C#)
  1. public partial class Form1 : Form
  2.     {
  3.         public Form1()
  4.         {
  5.             InitializeComponent();
  6.         }
  7.         Class1 g = new Class1();
  8.         static int e = 2;
  9.         Form2 f = new Form2(g);
  10.     }
- то есть, должно быть всё равно, в каком они следуют порядке. Инициализация, конечно, скорее всего будет происходить именно в этом порядке - но этот порядок не является алгоритмом, последовательностью действий - это всего лишь набор объявлений.

Строго говоря, это относится ко всем методам и полям класса (поле или метод могут быть объявлены уже после другого метода, который их использует). Надо понять, что они не выполняются в этом указанном порядке - а стало быть, одно поле и его инициализация_в_момент_объявления (когда ты объявляешь и сразу описываешь, как должно быть проинициализировано поле -- короче, как у тебя сделано) никак не может использовать значения других полей.

Если тебе нужно, чтобы таки использовало -- для того и существует конструктор-не-по-умолчанию у Form1:
Код: (C#)
  1. public partial class Form1 : Form
  2.     {
  3.         public Form1()
  4.         {
  5.             InitializeComponent();
  6.             f = new Form2(g);
  7.         }
  8.         Class1 g = new Class1();
  9.         Form2 f = null;
  10.     }

или, ещё лучше (потому что понятнее, что за чем следует):
Код: (C#)
  1. public partial class Form1 : Form
  2.     {
  3.         public Form1()
  4.         {
  5.             InitializeComponent();
  6.             g = new Class1();
  7.             f = new Form2(g);
  8.         }
  9.         Class1 g = null;
  10.         Form2 f = null;
  11.     }
« Последнее редактирование: 16-02-2011 23:15 от Вад » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #26 : 16-02-2011 23:21 » 

Сергей, то есть ты действительно уверен том, что если у тебя инстанция типа int,  то это переменная, а если типа Class1 то это уже объект? Или же ты думаешь, что они различаются по наличию/отсутствию new при создании? Те если я объявлю int i; то это переменная, а если int i= new int(); то это объект? Так получается? Другой разницы в приведённом тобой примере я не вижу.

Объясни пожалуйста, что в твоём понимании есть объект, а что переменная? Без этого понимания любой другой разговор не имеет смысла.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Сергей
Интересующийся

ua
Offline Offline

« Ответ #27 : 17-02-2011 00:37 » 

Джон, я так уже не думаю.
Объект - это не переменная, это её содержимое.
Класс — это конструктор, который позволяет создавать свои собственные пользовательские типы путем группирования переменных других типов, методов и событий.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #28 : 17-02-2011 07:25 » new

Цитата: Сергей
Класс — это конструктор, который позволяет создавать свои собственные пользовательские типы путем группирования переменных других типов, методов и событий.
Это справедливо для языков вроде Smalltalk, но это не справедливо для C++, C#, Java и т.п.

Конструктор предполагает какую-то динамику, какие-то действия в run time (и в Smalltalk, действительно, классы создаются в run time как экземпляры метакласса). В C# нет никакой динамики, класс - это описание типа. Разница здесь такая же, как между императивными и декларативными языками. Класс - это не кусок кода, который выполняется в процессе работы, класс - это лишь рекомендация компилятору, как ему сгруппировать данные, процедуры и функции, т.е. дальний аналог макроса.

Внутри класса есть конструктор - это процедура, которая выполняет действия в run time. И это конструктор объекта (экземпляра класса), а не самого класса. Этот конструктор вызывается лишь в те моменты, когда программист выделяет память под объект оператором new.

Наконец, static члены класса дополняют описание класса как объекта, существующего в единственном экземпляре (не имеющего ничего общего с объектами класса - экземплярами класса). И существует static конструктор для инициализации такого объекта. Этот конструктор тоже является процедурой, выполняемой в run time. Вызов этого конструктора формирует компилятор (т.е. программист не пишет вручную его вызов) и вызов происходит в run time один раз за всё время работы программы при первом обращении к классу (обращении по любому поводу - хоть указание переменной класса, хоть обращение к открытому статическому члену, хоть создание объекта этого класса или его потомков).
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines