views:

578

answers:

3

For a little background information, I've got an application that's running in a loop, and over ever tick it calls a method Tick. There's a bunch of classes that extend a base class and all have their own tick methods, and get added to a dependency chain so that say when class A gets called and it's chain has instances of B and C in it, B.Tick gets called, followed by C.Tick, and then finally A.Tick.

So in pseudo code my class kind of looks like this:

public class A : Super
Super b;
Super c;
ArrayList one;
ArrayList two;

tick(){
 one.Add(b.LastValue);
 two.Add(c.LastValue);
            ... do something with one and two ...
}

A(){
 b = new B(some other array list);
 c = new C(ref one);
}

B is working fine, and always gets the correct value. The problem is I guess you can't store a reference to another variable in a class, so when I do new C(ref one); and the contructor for C is setting a class variable to one, later on after one is updated in A it's like C no longer knows that its still supposed to be pointing towards one (which is now updated) and is just empty (like it originally was inside the constructor). Any idea on how to achieve what I'm looking to do, without having to use C# pointers and unsafe code? Thanks, hopefully it makes sense :)

Edit: Apparently people can't answer questions with confusing pseudo code that is completely unrelated to the actual question, so changed extends to :

Edit 2: C class

...
ArrayList local;
...
C(ref ArrayList one){
    local = one;
}

Tick(){
   LastValue = local[0] + 5; //not actual formula, just shows trying to use a referenced variable 
}
+2  A: 

Since one is an ArrayList, you can only pass it as a reference. You are now apparently passing it as a reference-to-a-reference to the constructor. You may not need that ref.

But please show a more complete idea of what you are trying to accomplish.

Edit:

After seeing your C class, there is no need for the ref. c will share the instance of the ArrayList that A calls one.

This seems to boil down to the general referencetype/valuetype issue in .NET. To summarize:

  • instances of objects do not have a name and cannot (physically) be passed as parameter at all.
  • you always access an instance through a reference. In your code, one (2x) , two, local are all references to Arraylist instances.
  • the references themselves behave like valuetypes, ie assignment means copying.

To learn more about referencetypes/valuetypes, search for 'copy semantics' and avoid postings that start with 'valuetypes exist on the stack'.

Henk Holterman
"Since one is an ArrayList, you can only pass it as a reference" should be replaced by "Since one is an ArrayList, you can only pass its reference" as you don't actually pass "it" as anything. You're passing its reference by value (or by reference if its `ref`).
Mehrdad Afshari
Mehrdad, literally correct but I tend to shorten the "pass it's reference by value" as appropriate.
Henk Holterman
In other words (if I may): passing it with `ref` gives the body of the method a way to change the actual object the calling variable is pointing at. Not passing it as `ref` and assigning a different object to the parameter, will not harm the passing variable. This is different from changing the members of the object that is passed, because both sides are pointing at the same object.
Abel
A: 

you can't store a reference to another variable in a class

You can, people do it all the time. Simply assign it to a (private) field.

so when I do new C(ref one); [snip /] later on after one is updated in A it's like C no longer knows that its still supposed to be pointing towards one

Actually, it does know that, but you should assign one to a member field. Assigning to objects is nothing more then setting a reference to the object. Changing the object, changes them everywhere you've assigned it:

class A
{
    public string Hello { get; set; }
}

class C
{
    private A myA;
    public C(A a) { myA = a; }
    public A GetMyA() { return myA; }
}

// somewhere else:
A someA = new A();
someA.Hello = "Hello World";
C someC = new C(someA);
someA.Hello = "Other World";
Console.WriteLine(someC.GetMyA().Hello);

// this will print "Other World" and not "Hello World" as you suggest

PS: since you were posting pseudocode, I hope you don't mind me simplifying it a bit. If I misunderstood your question, then please disregard (and perhaps clarify, if possible).

PPS: rereading your (edited) code and still trying to figure out what the problem is, there seems to be nothing that prevents C in your code from keeping a member with a reference to A and calling a.Add will obviously reflect the member variable in c as well. Indeed, no need for ref here.

Abel
A: 

There's nothing to prevent you from doing this. Whether or not it's a good idea is another question though. In general, I'd recommend trying to avoid changing state between method calls if you can avoid it. Of course, the key expression there is "if you can avoid it". :-)

Jason Baker