:)
    Find out what I'm doing, Follow Me :)

Wednesday, April 1, 2009

Changing Fields in a Boxed Value Type

Hi guys!

This will be my first topic. I hope it will be useful.

Changing Fields in a Boxed Value Type

In many cases, we must get a reference to an instance of a value type. Someone will say “But we already have generics”.

Yes we have generics, but still has cases (if you start working on project, which has been written on Visual Studio 2003 ) in which you should use a mechanism called boxing .

I created a structure (it is of value type).


struct MyPoint
{
public int X { get; set; }
public int Y { get; set; }

public void ChangeProperties(int x, int y)
{
this.X = x;
this.Y = y;
}

public override string ToString()
{
string message = string.Format("X - {0}, Y - {1}", X, Y);
return message;
}
}

What happens when an instance of a value type is boxed?


MyPoint p = new MyPoint();
p.X = 1;
p.Y = 1;
object obj = p;

1. Memory is allocated from the managed heap

2. The value type's fields are copied to allocated heap memory

3. The address of the object is returned


Is it possible to change fields of already boxed value type ?


Let’s see :)


MyPoint p = new MyPoint();
p.X = 1;
p.Y = 1;
Console.WriteLine(p); // Displays X - 1, Y - 1

p.ChangeProperties(2, 2);
Console.WriteLine(p); // Displays X - 2, Y - 2

object obj = p;
Console.WriteLine(obj); // Displays X - 2, Y - 2

((MyPoint)obj).ChangeProperties(3, 3);
Console.WriteLine(obj); // ! Displays X - 2, Y - 2


When I casting obj to a MyPoint (made operation unboxing) and call ToString() method I expect the following result [ X - 3, Y – 3]. Why this result is obtained ?

Because casting obj to a MyPoint unboxes obj and copies the fields in the boxed MyPoint to a temporary MyPoint on the thread's stack! The X and Y fields of this temporary point are changed to 3 and 3.


How to change fields of unboxed object?


With interface and this interface defining a ChangeProperties method



public interface IChangeBoxedPoint
{
void ChangeProperties(int x, int y);
}

struct MyPoint: IChangeBoxedPoint
{
public int X { get; set; }
public int Y { get; set; }

public void ChangeProperties(int x, int y)
{
this.X = x;
this.Y = y;
}

public override string ToString()
{
string message = string.Format("X - {0}, Y - {1}", X, Y);
return message;
}
}


MyPoint p = new MyPoint();
p.X = 1;
p.Y = 1;
Console.WriteLine(p); // Displays X - 1, Y - 1

p.ChangeProperties(2, 2);
Console.WriteLine(p); // Displays X - 2, Y - 2

object obj = p;
Console.WriteLine(obj); // Displays X - 2, Y - 2

((MyPoint)obj).ChangeProperties(3, 3);
Console.WriteLine(obj); // ! Displays X - 2, Y - 2

((IChangeBoxedPoint)obj).ChangeProperties(3, 3);
Console.WriteLine(obj); // Displays X - 3, Y - 3

MyPoint myPoint = ((MyPoint)obj);
Console.WriteLine(myPoint); // Displays X - 3, Y - 3


The code is almost identical to the previous version, but the ChangeProperties

method is defined by the IChangeBoxedPoint interface and the MyPoint type now implements

this interface. I cast the object to an IChangeBoxedPoint. Now this is change the boxed MyPoint's X and Y fields. The interface method ChangeProperties has allowed me to

change the fields in a boxed MyPoint object.