-1

Given that there is a class called Point with a float x and float y component.

class Point
{
    public double x;
    public double y;
    public Point(double x, double y)
    {
        this.x = x;
        this.y = y;
    }
    public Point()
    {
        x = y = 0;
    }
    public override string ToString()
    {
        return string.Format("({0:F2},{1:F2})", x, y);
    }
}

Why in the mystery1 function didn't the point p1 get updated to be (11.00, 11.00) since p.x is 11 from the first line?

{
    Point p1 = new Point(11, 22);
    Point p2 = p1;
    int n1 = 33;
    int n2 = n1;

    mystery1(p1, n1);
    Console.WriteLine("n1 = {0}, n2 = {1}", n1, n2);
    Console.WriteLine("p1 = {0}, p2 = {1}", p1, p2);

    mystery2(p2, n2);
    Console.WriteLine("n1 = {0}, n2 = {1}", n1, n2);
    Console.WriteLine("p1 = {0}, p2 = {1}", p1, p2);
}

static void mystery1(Point p, int n)
{
    n = (int)p.x;
    p = new Point(n, n);
}

static void mystery2(Point p, int n)
{
    p.x = 77;
    n = 88;
}
Vso
  • 21
  • 1
  • 8
  • I think that changing addresses doesn't affect parameters. –  Sep 29 '16 at 06:22
  • 4
    You should read https://msdn.microsoft.com/de-de/library/0f66670z.aspx, in particular the link for `ref`- and `out`-parameter. In Short: all parameters in C# are passed by value, thus when you re-assign a reference-type changes to that variable (or more precise to the object this variable referes to) are not reflected in the original reference. – MakePeaceGreatAgain Sep 29 '16 at 06:22
  • `static void mystery1(Point p, int n) { n = (int)p.x; p = new Point(n, n); }` isn't it because you're using a void function? voids have no return value. So p1 won't be updated. – Roy123 Sep 29 '16 at 06:30
  • @Roy_Dorsthorst Even if the method wasn´t `void` the values were not updated. – MakePeaceGreatAgain Sep 29 '16 at 06:30
  • @HimBromBeere but you could assign the function to p1 and have it return a Point right? – Roy123 Sep 29 '16 at 06:31
  • @Roy_Dorsthorst Sure, that´s possible. – MakePeaceGreatAgain Sep 29 '16 at 06:33
  • 1
    do you refer to the `System.Point`-struct or do you have an own class called `Point`? – MakePeaceGreatAgain Sep 29 '16 at 06:33
  • @HimBromBeere then why for mystery2 p2 got updated to (77.00, 11.00)? – Vso Sep 29 '16 at 06:34
  • @HimBromBeere I have an own class called Point – Vso Sep 29 '16 at 06:34
  • Please see the marked duplicate for the answer, in particular a discussion of how parameter passing in C# works. You are passing the `p1` reference by value, which means that when you assign a new value to the parameter `p`, it changes only the local parameter value, not the variable that was used to pass the original reference. If you want to change the original reference, you need to use `ref`. – Peter Duniho Sep 29 '16 at 06:38
  • see my answer for `mystery2`. – MakePeaceGreatAgain Sep 29 '16 at 06:38
  • 1
    See [Why are mutable structs “evil”?](http://stackoverflow.com/questions/441309/) _Edit:_ I retract this comment since this is about passing (references to) objects by value. – Jeppe Stig Nielsen Sep 29 '16 at 06:38
  • @JeppeStigNielsen: there are no structs here – Peter Duniho Sep 29 '16 at 06:39
  • @JeppeStigNielsen Although your link is always good in this case it won´t apply because OP has an own class `Point`. – MakePeaceGreatAgain Sep 29 '16 at 06:39

2 Answers2

1

Point is a value type. so when you call a method with a point as parameter, you have a new instance of the point in the method. So you are changing the values not on that instance that you have in the main method.

Have a look at the ref keyword: https://msdn.microsoft.com/en-us/library/0f66670z.aspx

Also at the moment you make a new instance with new Point(n, n); you create even one more instance of point . You main method still points to the old object which is not getting changed.

Also I would recommend that you have a general look at the differences between value and complex types like here: https://msdn.microsoft.com/en-us/library/34yytbws(v=vs.100).aspx or here: https://msdn.microsoft.com/en-us/library/s1ax56ch.aspx

Boas Enkler
  • 12,264
  • 16
  • 69
  • 143
1

In C# all paramaters are passed by value, even references.

That means when you pass an instance of a class to a method you pass the reference of that instance as value. Imagine the reference (similar to a pointer) is simply the adress of an instance within the stack stored into a string (it´s not a string, but for simplicity let´s assume so). Now when you change that string what should happen to the outside? Nothing, because the string is just a value, it does not have anything to do with your actual referenced instance. This sounds weird, but that´s it. In your msyter1-method you simply re-assign this reference to a new instance, however you simply change the value of that reference, not the reference itself.

You could do this by passing the class by reference`:

static void mystery1(ref Point p, ref int n)

Now changes within the method are reflected to the outer of the method.

In mystery2 there´s a difference and you won´t need the ref-keyword for your Point-class, because you´re not changing the reference itself but a property of the referenced instance. However this does not apply to the integer-argument which is of course a value-type and thus must be passed by ref to be updated outside your method also:

static void mystery2(Point p, ref int n)
MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111