0

Let's look at the following code.

struct SPoint
{
    public int x;
    public int y;

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

class Test
{

    public static void Main()
    {
        SPoint s = new SPoint(3, 4);
        object o = s;
        ((SPoint) o).x = 5;
    }
}

Why isn't the last assignment possible? What is the reason for such behaviour?

Tamir Vered
  • 10,187
  • 5
  • 45
  • 57
bottaio
  • 4,963
  • 3
  • 19
  • 43
  • 1
    Side note: Your struct is mutable. Check out http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil – Eric J. Oct 07 '15 at 18:44

2 Answers2

1

See MSDN:

The result of an unboxing conversion is a temporary variable. The compiler prevents you from modifying such variables because any modification would go away when the temporary variable goes away. To fix this, declare a new value-type variable to store the intermediate expression, and assign the result of the unboxing conversion to that variable.

AlexD
  • 32,156
  • 3
  • 71
  • 65
1

Since s is a struct (a.k.a: a value type), (SPoint)o is a copy of the data:

From the C# language spec (§1.3, "Types and Variables"):

When a value of a value type is converted to type object, an object instance, also called a “box,” is allocated to hold the value, and the value is copied into that box. Conversely, when an object reference is cast to a value type, a check is made that the referenced object is a box of the correct value type, and, if the check succeeds, the value in the box is copied out.

The language protects you from changing the data of the cloned value type without putting it in a variable first, since you might think that you are changing the original s.x value while you are changing it's temporary (not - variabled) clone, unlike unsafe languages like C++/CLI where this kind of assignments might be allowed.

If you want, you are able to explicitly create a new variable and do your manipulations in it:

SPoint cloneOfS = ((SPoint)o);
cloneOfS.x = 5;
Tamir Vered
  • 10,187
  • 5
  • 45
  • 57