the informal ramblings of a formal language researcher

Thursday, August 25, 2005

C#, pass-by-value, pass-by-reference

Here's a nice little snippet of C# for you.
using System;

namespace InterfaceSample {
public delegate void Changed();
interface IPoint {
int X { get; set; }
int Y { get; set; }
}

struct Point: IPoint {
private int xValue, yValue;
public int X { get { return xValue; } set { xValue = value; } }
public int Y { get { return yValue; } set { yValue = value; } }
}

public class EntryPoint {
public static int Main() {
String formatstr = " p1.X: {0}, p1.Y: {1}, p2.X: {2}, p2.Y: {3} ip1.X: {4}, ip1.Y: {5}, ip2.X: {6}, ip2.Y: {7}";

Point p1 = new Point();
p1.X = p1.Y = 42;
IPoint ip1 = p1;
Point p2 = (Point) ip1;
IPoint ip2 = ip1;

Console.WriteLine(formatstr, p1.X, p1.Y, p2.X, p2.Y, ip1.X, ip1.Y, ip2.X, ip2.Y);
p1.X = p1.Y = 21; Console.WriteLine("p1.X = p1.Y = 21;");
Console.WriteLine(formatstr, p1.X, p1.Y, p2.X, p2.Y, ip1.X, ip1.Y, ip2.X, ip2.Y);
ip1.X = ip1.Y = 84; Console.WriteLine("ip1.X = ip1.Y = 84;");
Console.WriteLine(formatstr, p1.X, p1.Y, p2.X, p2.Y, ip1.X, ip1.Y, ip2.X, ip2.Y);
return 0;
}
}
}
In C#, classes and interfaces can have properties, which have usage syntax similar to fields but semantics similar to methods. In the interface, you just declare the property name and whether it has getters/setters; in the class, you then define the behavior you want for the property.

In C#, you can declare struct types, which are value types in the language. This means that they are passed by value. However, they are not immutable.

In C#, a struct type can implement an interface. Ah, what fun.

Here's the output of the above program:
  p1.X: 42, p1.Y: 42, p2.X: 42, p2.Y: 42 ip1.X: 42, ip1.Y: 42, ip2.X: 42, ip2.Y: 42
p1.X = p1.Y = 21;
p1.X: 21, p1.Y: 21, p2.X: 42, p2.Y: 42 ip1.X: 42, ip1.Y: 42, ip2.X: 42, ip2.Y: 42
ip1.X = ip1.Y = 84;
p1.X: 21, p1.Y: 21, p2.X: 42, p2.Y: 42 ip1.X: 84, ip1.Y: 84, ip2.X: 84, ip2.Y: 84


The mutation to p's properties is not propagated over to ip, which looks odd to a Java programmer like me. This is because the assignment ip1 = p1 makes a copy of p1 when it "boxes" it into ip1.

And even odder, given the previous paragraph, the mutations to ip1 are carried over to ip2. Actually, this isn't so odd, since ip1 is an interface after all, that might ("must", considering boxing?) be implemented by an object, and therefore the assignment must copy a reference to the object.

Finally, you can copy from the interface back to a Point, but this requires a cast. This makes sense (see previous paragraph).

In the end, I don't think I have a big problem with value types. Its just the mutable value types that I get nervous about, because then you actually need to start thinking about the copy/reference semantics.

1 comment:

Roy T. said...

Nice article and just what I needed to get my mind straight :-)

Followers