开发者

Instantiating each of the two classes in one another

I have a C# class question which I hope to get some help with. I have one class called CountdownUserControl. There are a number of functions within this class. I then have another class called Min. There are certain things I need in this form within CountdownUserControl class so I create an instance of it within CountdownUserControl:

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

However within the Min class I also would like to use a function which is contained within the CountdownUserControl class - however I cannot create an instance of it within the Min class such as

public partial class Min : Form
{
    private开发者_开发百科 CountdownUserControl CU = new CountdownUserControl();

so that within Min class I could do CU.Method_I_want();

as this will give a stackoverflow. Does anyone know a solution around this? Thanks for your time.


Classes and methods

Classes shouldn't just been seen as a collection of methods, when they are created ('instantiated') with new, they become actual objects that should be treated as such.

You need to re-think your strategy and instead simply reference a Min or CoundownUserControl object. What does each one represent? You are suggesting that the UserControl (a part of a Form) needs to have its own Form created for it - that's not the case. The Form is the object that creates the UserControl. The UserControl can access the Form by using the ParentForm property.

The StackOverflow

When you do this: new Min() you are creating a new Min object. Then, in Min, when you do this: new CountdownUserControl() you are creating a new CoundownUserControl object. Which in turn creates a new Min object, and so on and so forth.

How to fix your problem

Simply put, use Min min = (Min)this.ParentForm; within the user control if you are sure the user control is on a Form whose type is Min.

And finally/additionally, you should not create the instance of CountdownUserControl yourself unless you are going to set the properties and add it to the Controls collection of the form within your code. Instead, build your project, drag-and-drop the CountdownUserControl onto your form - a property to access the control will be created on your Min class automatically, called countdownUserControl1.


All these answers are great, but you should also consider the fact that cyclic dependencies are generally really difficult to work with. Your classes should be somewhat isolated units with a single purpose. They should be loosely coupled from each other. If you redesign your classes to eliminate cyclic dependencies and follow these guidelines, you will write better and more maintainable code in general and will have less issues like this in the first place.


There surely are plenty of solutions to this. An easy one would be to pass the current Min to CountdownUserControl in its constructor (or vice versa):

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

When you are facing these kind of problems, there probably is something wrong with your class structure, though. Maybe you could split some of the functionality out of your classes into a new one to avoid this problem.


Instead of instantiating a new Min class every time, you could set the value of it in a constructor.

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


Is CountdownUserControl going to be on the Form Min? Why would you instantiate the form from the control, and not the reverse? Shouldn't the Countdown control be on the form? Then you could instantiate the form, initialize the control, and then access the function.


The problem here is that whenever a CountdownUserControl is created, it tries to create a new Min, but whenever a new Min is created, it tries to create a new CountdownUserControl. This process could continue indefinitely and therefore the stack is blown.

The solution is to inject the instance of CountdownUserControl into Min (Or vice versa, depending on what gets created first).

So CountdownUserControl will look like this:

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

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

...and Min will look like this:

public partial class Min : Form
{
    private CountdownUserControl CU;

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


Do not create a form in the user control. Add it as a dependency:

public partial class CountdownUserControl : UserControl
{
    private Min _Min;

    public CountdownUserControl(Min parentForm);

And then use it in your form:

public partial class Min : Form
{
    private CountdownUserControl CU;

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

Update

A more suitable solution would be to break out the common functionality from the two classes and put them in separate classes. Read up on single responsibility principle. I got a post about it in my blog.


You can pass in an instance of your CountdownUserControl to your Min class (via an additional constructor parameter or via a property).

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

    public CountdownUserControl Countdown {get;set;}
}

Since this is a form you probably want to go with the property so as not to break the designer.

I won't speak to whether or not this is proper form (hopefullt you are using something like PresentationModel or MVC), as I do know tehre are times code like this is required.

Now as has been pointed out, if you plan on showing the user control in the form then a different solution should be adopted. But it all depends on how you are planning on what you are doing with the form. If you are for example showing teh form in a dialog keeping a class level reference is a bad idea since once closed the form will be disposed.

A little more detail would get you closer to a fully correct answer.


However within the Min class I also would like to use a function which is contained within the CountdownUserControl class - however I cannot create an instance of it within the Min class such as

Is it really necessary that mentioned function is member of CountdownUserControl?

Could you reveal more of public interface of your classes? If the function has no reference to instance of CountdownUserControl consider changing it to static. Else try to design new class named e.g. CountdownState whose instance may be shared among both CountdownUserControl and Min.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜