42

I have a "meter" class. One property of "meter" is another class called "production". I need to access to a property of meter class (power rating) from production class by reference. The powerRating is not known at the instantiation of Meter.

How can I do that?

public class Meter
{
   private int _powerRating = 0; 
   private Production _production;

   public Meter()
   {
      _production = new Production();
   }
}
starball
  • 20,030
  • 7
  • 43
  • 238
Jean Duprez
  • 423
  • 1
  • 4
  • 4
  • Possible duplicate of [What's the best way of accessing field in the enclosing class from the nested class?](http://stackoverflow.com/questions/185124/whats-the-best-way-of-accessing-field-in-the-enclosing-class-from-the-nested-cl) – Jim Fell May 27 '16 at 18:29
  • 2
    @JimFell This does not involve nested classes at all – Rob May 28 '16 at 04:43

7 Answers7

52

Store a reference to the meter instance as a member in Production:

public class Production {
  //The other members, properties etc...
  private Meter m;

  Production(Meter m) {
    this.m = m;
  }
}

And then in the Meter-class:

public class Meter
{
   private int _powerRating = 0; 
   private Production _production;

   public Meter()
   {
      _production = new Production(this);
   }
}

Also note that you need to implement an accessor method/property so that the Production class can actually access the powerRating member of the Meter class.

Christian
  • 4,261
  • 22
  • 24
  • 1
    What if the two classes are in different assemblies, and Meter-containing assembly has a VS2010 project reference to the Production-containing assembly? – Snowy Jun 12 '11 at 03:20
  • 2
    @Snowy: Since cyclic references aren't possible, you'd need to rearrange your implementation and move one class to another assembly (or duplicate the class, if nothing else helps). – Christian Jun 14 '11 at 05:53
38

I wouldn't reference the parent directly in the child objects. In my opinion the childs shouldn't know anything about the parents. This will limits the flexibility!

I would solve this with events/handlers.

public class Meter
{
    private int _powerRating = 0;
    private Production _production;

    public Meter()
    {
        _production = new Production();
        _production.OnRequestPowerRating += new Func<int>(delegate { return _powerRating; });
        _production.DoSomething();
    }
}

public class Production
{
    protected int RequestPowerRating()
    {
        if (OnRequestPowerRating == null)
            throw new Exception("OnRequestPowerRating handler is not assigned");

        return OnRequestPowerRating();
    }

    public void DoSomething()
    {
        int powerRating = RequestPowerRating();
        Debug.WriteLine("The parents powerrating is :" + powerRating);

    }

    public Func<int> OnRequestPowerRating;
}

In this case I solved it with the Func<> generic, but can be done with 'normal' functions. This why the child(Production) is totally independent from it's parent(Meter).


But! If there are too many events/handlers or you just want to pass a parent object, i would solve it with an interface:

public interface IMeter
{
    int PowerRating { get; }
}

public class Meter : IMeter
{
    private int _powerRating = 0;
    private Production _production;

    public Meter()
    {
        _production = new Production(this);
        _production.DoSomething();
    }

    public int PowerRating { get { return _powerRating; } }
}

public class Production
{
    private IMeter _meter;

    public Production(IMeter meter)
    {
        _meter = meter;
    }

    public void DoSomething()
    {
        Debug.WriteLine("The parents powerrating is :" + _meter.PowerRating);
    }
}

This looks pretty much the same as the solution mentions, but the interface could be defined in another assembly and can be implemented by more than 1 class.


Regards, Jeroen van Langen.

Jeroen
  • 449
  • 4
  • 2
10

You would need to add a property to your Production class and set it to point back at its parent, this doesn't exist by default.

bwarner
  • 872
  • 1
  • 5
  • 12
3

Why not change the constructor on Production to let you pass in a reference at construction time:

public class Meter
{
   private int _powerRating = 0; 
   private Production _production;

   public Meter()
   {
      _production = new Production(this);
   }
}

In the Production constructor you can assign this to a private field or a property. Then Production will always have access to is parent.

Rob Levine
  • 40,328
  • 13
  • 85
  • 111
0

You could maybe add a method to your Production object called 'SetPowerRating(int)' which sets a property in Production, and call this in your Meter object before using the property in the Production object?

Gary Willoughby
  • 50,926
  • 41
  • 133
  • 199
  • I think this violates KISS; having to remember to call a function before calling a property makes it overly complicated IMO. – Matt Ellen Dec 21 '09 at 14:21
  • True, the above design sounds as if it needs a whole re-think. I just supplied a solution and it's probably not the best one. – Gary Willoughby Dec 24 '09 at 13:20
0

I would give the parent an ID, and store the parentID in the child object, so that you can pull information about the parent as needed without creating a parent-owns-child/child-owns-parent loop.

WannabeMe
  • 41
  • 4
-4

something like this:

  public int PowerRating
    {
       get { return base.PowerRating; } // if power inherits from meter...
    }
Tony The Lion
  • 61,704
  • 67
  • 242
  • 415