According to MSDN (Section 11.3.6 of the C# spec):
Within an instance constructor of a struct,
this
corresponds to anout
parameter of the struct type, and within an instance function member of a struct,this
corresponds to aref
parameter of the struct type. In both cases,this
is classified as a variable, and it is possible to modify the entire struct for which the function member was invoked by assigning tothis
or by passingthis
as aref
orout
parameter.
I don't get it. How is this
different for a struct than for a class? Code examples are appreciated
Eric Lippert had a fabulous post on mutating readonly struct
s a while back that will really help clarify the issue for you. There's even a code example, and a quiz!
The salient point is that struct
s obey value semantics and class
es do not and so this
must mean something different for the two. this
is readonly
for a class
, but not for a struct
. The following code is legal
struct Point {
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public void DoGoTime() {
GoTime(ref this);
}
public static void GoTime(ref Point p) {
p.x = 100;
p.y = 100;
}
}
but is not if "struct
" is replaced by "class
."
When you're dealing with structs, you're dealing with value types.
In a class, "this" is a reference to the current instance. This lets you mutate the class instance by setting properties/fields on the class.
However, if you're in a struct, things act differently. When you're in a struct's method, "this" lets you mutate the struct. However, if you're using this in a method, you're almost always dealing with a copy of the "original" struct.
For example:
struct Test
{
int i;
void Mutate() {
this.i += 1;
}
}
When you use this:
void MutateTest(Test instance)
{
instance.Mutate();
}
{
Test test = new Test();
test.i = 3;
Console.WriteLine(test.i); // Writes 3
test.Mutate(); // test.i is now 4
Console.WriteLine(test.i); // Writes 4
MutateTest(test); // MutateTest works on a copy.. "this" is only part of the copy itself
Console.WriteLine(test.i); // Writes 4 still
}
Now, the stranger part - this is valid, and what that quote was saying:
struct Test
{
public Test(int value)
{
this.i = value;
}
int i;
void Mutate(int newValue) {
this = new Test(newValue); // This wouldn't work with classes
}
}
///
{
Test test = new Test();
test.i = 3;
Console.WriteLine(test.i); // Writes 3
test.Mutate(4);
Console.WriteLine(test.i); // Writes 4
Jason's answer and Eric's post show one aspect of this
which is interesting... but there's another which is even more alarming:
You can reassign this
within a method, even if the type is otherwise immutable.
To demonstrate it, we'll use a struct which is stored in a non-readonly variable, but which contains a readonly field:
using System;
public struct LooksImmutable
{
private readonly int value;
public int Value { get { return value; } }
public LooksImmutable(int value)
{
this.value = value;
}
public void GoCrazy()
{
this = new LooksImmutable(value + 1);
}
}
public class Test
{
static void Main()
{
LooksImmutable x = new LooksImmutable(5);
Console.WriteLine(x.Value);
x.GoCrazy();
Console.WriteLine(x.Value);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With