Инстанцирование каждого из двух классов друг в друге - PullRequest
3 голосов
/ 10 августа 2011

У меня есть вопрос класса C #, с которым я надеюсь получить помощь.У меня есть один класс под названием CountdownUserControl.В этом классе есть ряд функций.У меня тогда есть другой класс под названием Мин.Есть некоторые вещи, которые мне нужны в этой форме в классе CountdownUserControl, поэтому я создаю его экземпляр в CountdownUserControl:

public partial class CountdownUserControl : UserControl
{
    //-----------------------------------------------
    // Private data members
    //-----------------------------------------------
    private Min _Min = new Min();

Однако в классе Min я также хотел бы использовать функцию, которая содержится в CountdownUserControlкласс - однако я не могу создать его экземпляр в классе Min, например

public partial class Min : Form
{
    private CountdownUserControl CU = new CountdownUserControl();

, чтобы в классе Min я мог сделать CU.Method_I_want ();

, поскольку это дастпереполнение стека.Кто-нибудь знает решение вокруг этого?Спасибо за ваше время.

Ответы [ 9 ]

3 голосов
/ 10 августа 2011

Классы и методы

Классы не должны рассматриваться просто как набор методов, когда они создаются (создаются) с помощью new, они становятся реальными объектами, которые должны рассматриваться как таковые.

Вам необходимо переосмыслить свою стратегию и вместо этого просто указать Min или CoundownUserControl объект. Что каждый из них представляет? Вы предполагаете, что UserControl (часть Form) должен иметь свой собственный Form, созданный для него - это не так. Form - это объект, который создает UserControl. UserControl может получить доступ к Form с помощью свойства ParentForm.

StackOverflow

Когда вы делаете это: new Min() вы создаете новый Min объект. Затем в Min, когда вы делаете это: new CountdownUserControl() вы создаете новый CoundownUserControl объект. Который, в свою очередь, создает новый Min объект и так далее, и так далее.

Как исправить вашу проблему

Проще говоря, используйте Min min = (Min)this.ParentForm; в пользовательском элементе управления, если вы уверены, что пользовательский элемент управления находится на Form, тип которого Min.

И, наконец, / дополнительно, вы не должны создавать экземпляр CountdownUserControl самостоятельно, если не собираетесь устанавливать свойства и добавлять его в коллекцию Controls формы в вашем коде. Вместо этого создайте свой проект и перетащите CountdownUserControl на форму - свойство для доступа к элементу управления будет автоматически создано в вашем классе Min, которое называется countdownUserControl1.

1 голос
/ 10 августа 2011

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

1 голос
/ 10 августа 2011

Конечно, есть много решений для этого. Проще всего было бы передать текущий Min в CountdownUserControl в его конструкторе (или наоборот):

private Min min;
public CountdownUserControl(Min min)
{
     this.min = min;
}

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

0 голосов
/ 10 августа 2011

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

Решение состоит в том, чтобы внедрить экземпляр CountdownUserControl в Min (или наоборот, в зависимости от того, что создается первым).

Так CountdownUserControl будет выглядеть так:

public partial class CountdownUserControl : UserControl
{
    //-----------------------------------------------
    // Private data members
    //-----------------------------------------------
    private Min _Min;

    public CountdownUserControl(Min min)
    {
        _Min = min;
    }

... и Min будет выглядеть так:

public partial class Min : Form
{
    private CountdownUserControl CU;

    public Min()
    {
        CU = new CountdownUserControl(this);
    }
0 голосов
/ 10 августа 2011

Однако в классе Min я также хотел бы использовать функцию, которая содержится в классе CountdownUserControl - однако я не могу создать его экземпляр в классе Min, например

Действительно ли необходимо, чтобы упомянутая функция входила в CountdownUserControl?

Не могли бы вы рассказать больше о публичном интерфейсе ваших классов?Если функция не имеет ссылки на экземпляр CountdownUserControl, подумайте об изменении его на статический.В противном случае попробуйте разработать новый класс с именем, например, CountdownState, экземпляр которого может быть совместно использован как CountdownUserControl, так и Min.

0 голосов
/ 10 августа 2011

Вы можете передать экземпляр вашего CountdownUserControl вашему классу Min (через дополнительный параметр конструктора или через свойство).

public partial class Min: Form {
    public Min() {
        InitializeComponent();
    }

    public CountdownUserControl Countdown {get;set;}
}

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

Я не буду говорить о том, является ли это правильной формой (надеюсь, вы используете что-то вроде PresentationModel или MVC), поскольку я знаю, что временами такой кодтребуется.

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

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

0 голосов
/ 10 августа 2011

Не создавать формы в пользовательском элементе управления.Добавьте его как зависимость:

public partial class CountdownUserControl : UserControl
{
    private Min _Min;

    public CountdownUserControl(Min parentForm);

, а затем используйте его в своей форме:

public partial class Min : Form
{
    private CountdownUserControl CU;

    public Min()
    {
       CU = new CountdownUserControl (this);
    }

Обновление

Более подходящее решение будетбыть выделение общих функциональных возможностей из двух классов и поместить их в отдельные классы.Читайте по принципу единой ответственности.Я получил сообщение об этом в моем блоге .

0 голосов
/ 10 августа 2011

Будет ли CountdownUserControl в форме Min? Зачем вам создавать экземпляр формы из элемента управления, а не наоборот? Разве элемент управления обратным отсчетом не должен быть в форме? Затем вы можете создать экземпляр формы, инициализировать элемент управления и получить доступ к функции.

0 голосов
/ 10 августа 2011

Вместо того, чтобы каждый раз создавать новый класс Min, вы можете установить его значение в конструкторе.

public CountdownUserControl(Min min)
{
     _Min = min;
...
...