Method invocation on a struct?

According to the CIL spec the this pointer is passed by reference / as managed pointer. As Binary Worrier assumed this is a CIL feature.

According to the CIL spec the this pointer is passed by reference / as managed pointer. As Binary Worrier assumed this is a CIL feature. Instance and virtual methods of classes shall be coded to expect a reference to an instance of the class as the this pointer.By contrast, instance and virtual methods of value types shall be coded to expect a managed pointer (see Partition I) to an unboxed instance of the value type.

The CLI shall convert a boxed value type into a managed pointer to the unboxed value type when a boxed value type is passed as the this pointer to a virtual method whose implementation is provided by the unboxed value type. So from a high-level perspective a call to an instance method of a reference type (class) looks like this: MyClass myClass = MyClass_Constructor(); MyClass_MyInstanceMethod(myClass, myFirstParameter); // ^ // The "this" argument And a call to an instance method of a value type (struct) like this: MyStruct myStruct = MyStruct_Constructor(); MyStruct_MyInstanceMethod(ref myStruct, myFirstParameter); // ^ // The "this" argument.

1, though maybe it would be good to provide a dumbed down translation, too. Those last few sentences are fairly low level and dense. – Merlyn Morgan-Graham May 5 at 9:52 +1: Good find .

– Binary Worrier May 5 at 9:55 +1. What's important is that the value doesn't get boxed, which prevents performance penalties. – Groo May 5 at 9:56 Meryl, I added some pseudo code to describe what the difference is.

– Florian Greinacher May 5 at 10:01.

Florian is right; a few more details while we're on the subject: When we invoke a method on a object, then the reference of the object is passed implicitly to the method. Correct. One way to think about this is that a method call like: class C { int y; public void M(int x) { Console.

WriteLine(x + y); } } ... C c = new C(); c. M(10); is actually the same as class C { int y; public static void M(C _this, int x) { Console. WriteLine(x + _this.

Y); } } ... C c = new C(); C. M(c, 10); That is, every instance method has a hidden "this" parameter, and the method is "really" static. So my question is what happens when a method is invoked on a struct?

Is it similar to classes in this aspect? Yes. Instead of a reference to an instance, what is passed is an alias to the variable that contains the struct.

That's how struct methods can mutate the struct. (Of course, mutating a struct is a bad practice, but sometimes necessary. ) struct S { int y; public void M(int x) { Console.

WriteLine(x + y); } } ... S s = new S(); s. M(10); is logically the same as struct S { int y; public static void M(ref S _this, int x) { Console. WriteLine(x + _this.

Y); } } ... S s = new S(); S. M(ref s, 10); An interesting question then arises: what if the "receiver" is not a variable? (*) You can only take a ref to a variable.

Suppose you have: GetAnS(). M(10);? What happens then?

We make a variable for you. That becomes S temporary = GetAnS(); temporary. M(10); and now the receiver is a variable, so we can make the "hidden this parameter" an alias to it.(*) There are other interesting cases here as well, like what if the struct is mutable but the variable is readonly, and so on.

1 Eric Lippert +1 Thanks for the explanation. – Searock May 6 at 9:06.

I wrote a series of blog posts on exactly this subject a while back. In particular, simple-talk.com/community/blogs/simonc/a... In IL, you can store a managed pointer on the stack, which is like an object reference, except it can point at things other than object references. There are specific instructions to get a managed pointer to something, such as ldloca, which gets a pointer to a local variable, or ldelema, which gets a pointer to a particular element in an array.

These are safe pointers, as the garbage collector knows about them, and so changes them if the object you're pointing to is moved by the GC. Method calls on structs require a managed pointer to the struct (which can be anywhere in memory - on the stack, in an argument list, in another object on the heap) the method is to be executed on as the this pointer. Method calls on reference types require an object reference.

This causes some issues when calling methods on generic types, which can be either value or reference types. I have a look at that in later blog posts. One of the side effects of being able to use managed pointers to value types is that it is possible in IL to call a method on a boxed value type without having to unbox it: // you have a struct on the stack box MyStructType // this copies the value on the stack to an object on the heap unbox MyStructType // this returns a managed pointer to the value type instance in its boxed form.It doesn't copy the value itself back to the stack (despite the name) call instance void MyStructType::MyMethod().

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions