Main question is what are the implications of allowing the this keyword to be modified in regards to usefulness and memory; and why is this allowed in the C# language specifications?
The other questions/subparts can be answered or not if choose to do so. I thought answers to them would help clarify the answer to the main question.
I ran across this as an answer to What's the strangest corner case you've seen in C# or .NET?
public struct Teaser
{
public void Foo()
{
this = new Teaser();
}
}
I've been trying to wrap my head around why the C# language specifications would even allow this. Sub-part 1. is there anything that would justify having this be modifiable? Is it every useful?
One of the comments to that answer was
From CLR via C#: The reason they made this is because you can call the parameterless constructor of a struct in another constructor. If you only want to initialize one value of a struct and want the other values to be zero/null (default), you can write public Foo(int bar){this = new Foo(); specialVar = bar;}. This is not efficient and not really justified (specialVar is assigned twice), but just FYI. (That's the reason given in the book, I don't know why we shouldn't just do public Foo(int bar) : this())
Sub-part 2. I'm not sure I follow that reasoning. Can someone clarify what he meant? Maybe a concrete example of how it would be used?
EDIT (Disregard stack or heap main point is in regards to memory release or garbage collection. Instead of the int[] you could replace that with 262144 public int fields) Also from my understanding structs are created on the stack as opposed to the heap if this struct were to have a 1 Mb byte array field initialized as so
public int[] Mb = new int[262144];
Sub-part 3. does this ever get removed from the stack when Foo is called? To me it seems since the struct never went out of scope it would not be removed from the stack. Don't have time tonight to create a test case but maybe I will for this one tomorrow.
In the below code
Teaser t1 = new Teaser();
Teaser tPlaceHolder = t1;
t1.Foo();
Sub-part 4. Are t1 and tPlaceHolder occupying the same or different address space?
Sorry to bring up a 3 year old post but this one has really got my head scratching.
FYI first question on stackoverflow so if I got something wrong with the question kindly post a comment and I will edit.
After 2 days I'll put a bounty of 50 on this question even if I have a winner chosen in my mind already as I think the answer will require a reasonable amount of work to explain the questions.
this
needs to be aref
parameter otherwise you could never modify the current instance of astruct
by passing it to a method that mutates it becausestruct
are passed by value. So, we need to be able to pass the current instance byref
, and to do thatthis
has to be aref
parameter. In fact, the spec says it is. Once it'sref
, you can assign to it. 2. No, that's not right. The reason I gave in 1. is the reason. – Curiumstruct
are short-lived, sometimes they are not (if they are fields of a class, for example). Just because astruct
has a field that is long-lived does not mean that thestruct
itself is long-lived. Don't confuse scope and lifetime, it's an abuse of the terminology. "Scope" of a named variable means "the region of the program where I can refer to that variable by its simple name." – CuriumtPlaceHolder
andt1
are different storage locations. – Curium