4
class Player
{
   private Location location;

   public Location getLocation()
   {
        return location;
   }

    public void setLocation(Location location)
    {
        this.location = location;
    }
}

...

class Location
{
    int x,y,z;

    public Location(int x, int y, int z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public Location(Location location)
    {
        this.x = location.x;
        this.y = location.y;
        this.z = location.z;
    }


    public void updateLocation(Location location) //the fix..
    {
        this.x = location.x;
        this.y = location.y;
        this.z = location.z;
    }
}

Say.. you do

Player p1 = new Player();
Player p2 = new Player();
p1.setLocation(p2.getLocation());

Now the bug/problem occurs when you attempt to modify other persons location. Both players locations changes exactly the same, as they both now share the same location.

So of course this below will work just fine.

p1.setLocation(new Location(p2.getLocation()));

but the problem is it always creates a new object.. when I could just update the existing instance..? how do I update the existing instance on default without making my own methods like I did below to fix this.

I had to fix this using the method below (any way to do this by default without doing like this below)

    public void setLocation(Location location)
    {
        if (this.location == null)
            this.location= new Location(location);
        else
            this.location.updateLocation(location);
    }

Anyone knows any tricks I may not know about? Thanks.

SSpoke
  • 5,656
  • 10
  • 72
  • 124
  • 1
    You could make `Location` a struct. Then, it will be passed by value. This will work because your location object is basically a container for other value types, and is relatively small. – Joseph Yaduvanshi Jun 25 '11 at 20:55
  • it has other methods like .Equals() and such like .withinDistance(other Location) etc.. – SSpoke Jun 25 '11 at 20:57
  • 1
    You can add members to a struct. Just keep it small, and remember that the larger the struct, the more memory it takes up on the stack. Here's msdn's C# Programming Guide link for structs: http://msdn.microsoft.com/en-us/library/saxz13w4(v=VS.90).aspx – Joseph Yaduvanshi Jun 25 '11 at 21:02
  • Just a note not related to your question: in C#, you should use properties, instead of Java-like get and set methods. – svick Jun 25 '11 at 21:07
  • Why is creating a new object every time a problem? – svick Jun 25 '11 at 21:09
  • haha svick you picked up on what I wrote haha.. yah i don't like Properties style.. i know the power in them.. as you can debug variables!. Anyways I solved it.. guys it was a typo.. copy-constructor works properly now! Because svick why garbage collect a object which can be reused? creating objects is too much of a overhead this operation isn't heavy.. but it will be done over a thousand times every second.. (populated server). – SSpoke Jun 25 '11 at 21:11
  • @SSpoke, if it can be reused easily, sure why not. If it requires significant effort, you should put off doing that and actually do it only when you find out that it actually is a performance bottleneck. – svick Jun 25 '11 at 23:07
  • My problem is the same as this http://stackoverflow.com/questions/292676/is-there-a-workaround-for-overloading-the-assignment-operator-in-c – SSpoke Jun 26 '11 at 00:32

2 Answers2

7

Classes are reference types. When you call this:

p1.setLocation(p2.getLocation());

you are not passing instance data to the method but the reference to the instance. Reference is like managed pointer to heap (memory) where the instance's data are stored. That is quite important because otherwise all changes to instance's data would have only method scope. When you call this:

this.location = location;

you are assigning the reference not the data. It means that both location and this.location will point to the same block in the memory.

That is the essential point in C# programming. If you want data to be copied instead of referenced you must use structures instead of classes.

Anyway reassiging values from one instance to another instance is quite common task.

Edit:

You pointed that you don't want to create new object because of overhead.

  • Premature optimization is source of evil
  • Optimize where it make sense and where you see that it really make performance drop. Here you have some values about object instantiation on simple laptops.

Also saying that you don't like properties is strange - you are programming in C# so use it correctly otherwise your colleagues will not like you.

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • Sure in that link he created 7 million objects in a second but what happens when garbage collector comes around CPU will spike? – SSpoke Jun 25 '11 at 21:27
  • 7M is only the very first test which is slow down by `StopWatch` evaluation. The last test in comment was able to achieve 450M. GC impact is separate story which belongs to my first point - optimize when you have a problem. You can be sure that your code will contain much worse parts. – Ladislav Mrnka Jun 25 '11 at 21:56
  • Yup thanks i'll avoid optimizing until the product is done. about Properties it just feels odd using them they feel like variables which is a big plus.. but when you set them.. you cannot physically set it.. you must set it on a supporting variable which to me is very messy. Although thats exactly what I'm doing with the java/c/c++ style function/method calls.. atleast I know those are methods/functions with properties it's just strange. – SSpoke Jun 25 '11 at 22:10
  • Have you seen [auto properties](http://msdn.microsoft.com/en-us/library/bb384054.aspx)? – Ladislav Mrnka Jun 25 '11 at 22:12
  • yes forgot to mention that.. that is nice but how do I do something like this.. (all in same scope) `public string X { get; set { doSomething(value); this = value; //? X = value; //? } }` when I use `this` i don't imply the class where it resides i mean the actual Property (just messing around) – SSpoke Jun 25 '11 at 22:14
  • Auto property cannot have implemented setter. In such case you need full property backed with a field. – Ladislav Mrnka Jun 25 '11 at 22:26
0

Passing references around in .NET is essentially the same as Java. However.NET we have a few extra features.

For example the out and the ref params can be used to return values passed as arguments. e.g.

    public void SaveProductFeature(ref SaveCollection save)
    {
       SaveCollection.Product.ProductId = Product.Save(SaveCollection.Product);
    }
Nickz
  • 1,880
  • 17
  • 35