Imagine we have a mutable struct (yes, don\'t start):
public struct MutableStruct
{
public int Foo { get; set; }
public override string
Even without unsafe code, pure C#:
using System;
internal interface I {
void Increment();
}
struct S : I {
public readonly int Value;
public S(int value) { Value = value; }
public void Increment() {
this = new S(Value + 1); // pure evil :O
}
public override string ToString() {
return Value.ToString();
}
}
class Program {
static void Main() {
object s = new S(123);
((I) s).Increment();
Console.WriteLine(s); // prints 124
}
}
In C#, this reference inside value types instance methods actually is ref-parameter (or out-parameter in value type constructor, and that is why this can't be captured into closures, just like ref/out parameters in any methods) and can be modified.
When struct instance method is invoked on unboxed value, this assignment will effectively replace value at the call site. When instance method is invoked on boxed instance (via virtual call or interface call like in the example above), ref-parameter is pointed to the value inside the box object, so it is possible to modify boxed value.