ghowell
ghowell

Reputation: 5

Accessing a field of outer class from inner class

I have an inner class to contain methods of my project; and I want to use the Form class event handlers to call my methods from the inner class; but I am having trouble accessing members of the outer class such as label1, label2, label3 etc.

How do I access a field of an outer class?

I'm trying to make an association inside the constructor :

public partial class Form1 : Form
{
    // declare inner class here
    public MachineClass machineObj = new MachineClass();

    public class MachineClass        
    {
        int fruit1, fruit2, fruit3, fruitvalue1, fruitvalue2, fruitvalue3;
        public void spinslot()
        {
            Random player = new Random();

            fruit1 = player.Next(10);//generates a number between 0 and 9
            fruit2 = player.Next(10);//generates a number between 0 and 9
            fruit3 = player.Next(10);//generates a number between 0 and 9
            fruitvalue1 = fruit1 + 1;// 
            fruitvalue2 = fruit2 + 1;// 
            fruitvalue3 = fruit3 + 1;// 
            label1.ImageIndex = fruit1;//display image in label - uses image list
            label2.ImageIndex = fruit2;//display image in label - uses image list
            label3.ImageIndex = fruit3;//display image in label - uses image list

        }
    }
}

Upvotes: 0

Views: 1472

Answers (2)

Enigmativity
Enigmativity

Reputation: 117154

Here is what you really need to do to make this work and to do so with a better OO design.

First-up, define the internal MachineClass like this:

public class MachineClass        
{
    private int fruit1, fruit2, fruit3;

    public delegate void FruitUpdate(int value);

    public event FruitUpdate FruitUpdate1;
    public event FruitUpdate FruitUpdate2;
    public event FruitUpdate FruitUpdate3;

    public void spinslot()
    {
        Random player = new Random();

        fruit1 = player.Next(10);
        fruit2 = player.Next(10);
        fruit3 = player.Next(10);

        if (this.FruitUpdate1 != null) this.FruitUpdate1(fruit1);
        if (this.FruitUpdate2 != null) this.FruitUpdate2(fruit2);
        if (this.FruitUpdate3 != null) this.FruitUpdate3(fruit3);
    }
}

The FruitUpdate delegate allows the definition of three events that can let external users of this class know when updates to the fruit values occur. When updates to the fruit values occur we check that there are handlers attached to the event and then just call the events. The MachineClass does not need to know that there is anything listening.

Now the Form1 class looks a bit like this:

public partial class Form1
{
    public MachineClass machineObj = new MachineClass();

    public void Form1_Load()
    {
        this.machineObj.FruitUpdate1 += v => label1.ImageIndex = v;
        this.machineObj.FruitUpdate2 += v => label2.ImageIndex = v;
        this.machineObj.FruitUpdate3 += v => label3.ImageIndex = v;
    }

    public class MachineClass
    {
        /* definition from above */
    }

}

Here the Form1 class creates the instance of MachineClass and then attaches handlers to each of the fruit update events. This allows the labels to be updated without the MachineClass being aware of them at all!

Upvotes: 0

furkle
furkle

Reputation: 5059

One way, off the top of my head, to do this, would be for the parent class to keep reference to the child, and vice versa. So for this class structure:

class ParentClass
{
    public ParentClass() 
    {
         this.child = new ChildClass(this);
    }
    public ChildClass child { get; set; }

    class ChildClass
    {
        public ParentClass Parent { get; set; }
        public ChildClass(ParentClass par)
        {
            this.Parent = parent;
        }
    }
}

then any time you wanted to access a field in the parent class from the subclass, you could just call .Parent.Whatever. Granted, this forces you to instantiate both at the same time, so I'm not sure if it's that great a way of accomplishing what you intend, nor whether it'll work for your purposes.

Edit: Alternately, you could use ParentClass as a factory of sorts for ChildClass, like so:

 class ParentClass
 {
     public ParentClass() { }

     public class ChildClass
     {
         public ParentClass Parent { get; set; }
         public ChildClass(ParentClass par)
         {
             this.Parent = par;
         }
     }

     public ChildClass GetChild()
     {
         return new ChildClass(this);
     }
 }

and you could instantiate an unlimited number of related ChildClasses from any given ParentClass, and calling .Parent from any ChildClass would refer to the ParentClass from which it was created.

I'd like to make a note, though, that in my experience I've found very few uses for inner classes, and I can't think of a single time where the above class designs would have benefited me. Particularly given that your example doesn't really seem like it's doing anything special, it seems like you'd be better off constructing a normal class outside the scope of your Form class and passing data to it as needed, rather than trying to create a convoluted inner class with a parent/child relation.

Upvotes: 1

Related Questions