Assignment of a struct value to this keyword

爱⌒轻易说出口 提交于 2019-11-29 00:09:17
MattDavey

This is a very little known feature of C# - this allows a struct to overwrite its own data.

As far as practical application goes, you're not going to find many uses for this..

struct MyStruct
{
    int a = 1;
    int b = 2;
    int c = 3;

    public void Mutate()
    {
        a = 10;
        b = 20;
        c = 30;
    }

    public void Reset()
    {
        a = 1;
        b = 2;
        c = 3;
    }

    public void Reset2()
    {
        this = new MyStruct();
    }

    // The two Reset methods are equivilent...
}

Thinking about it more, there's a fundamental difference in what "this" means when you're dealing with value types vs reference types.

When you call "this" on a reference type - what you get is a pointer that lives on the stack, you don't actually get the object itself. The pointer implicitly dereferences back to the object on the heap, which abstracts the indirection. Now if assigning to this in classes were possible, and you'd have said something like this = new MyReferenceType(), you'd have changed the pointer to point to a different heap object in the current scope - you wouldn't have changed the original object itself in the heap, nor would it have caused any other references/pointers to refer the new heap object. Its very likely that as soon as your mutated pointer would have gone out of scope - the new heap object you'd have created would have been subject to garbage collection.

When you call "this" on a value type - you are getting the actual object, not a reference or pointer. There is no indirection so you are free to overwrite the raw bits at this memory location (which is exactly what the default constructor does).

Just a guess:

Every class is a reference type meaning that the memory is allocated in the heap and the caller gets access to the actual data through the pointer. For example:

Customer c1 = new Customer('CUSTID');   // "Customer" is a reference type 
Customer c2 = c1;   // "c1" and "c2" points to the same memory within the heap

Every struct is a value type meaning that the memory is allocated in the stack and the caller deals with the actual instance rather than with the reference to that instance. For example:

Customer c1 = new Customer('CUSTID');    // "Customer" is a value type 
Customer c2 = c1;   // New memory gets allocated for "c2" within the stack

Considering your example:

this = new Customer();

Performing the following operation on a struct simply initializes it with zero values:

mov eax,dword ptr [ebp-3Ch] ; Save pointer to "ebp-3Ch" in EAX register
xor edx,edx                 ; Clear EDX register
mov dword ptr [eax],edx     ; Write "zero" by address containing in EAX

I don't know why it's not possible with reference types but my guess is that in will require traversing of the entire object graph to "reset" it completely (which might be not an easy task). I assume that this will become worth in case of circular references.

Again, this is just my thoughts and I'd very much like someone to either prove or discard (with an explanation, of course) them.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!