When we invoke a method on a object, then the reference of the object is passed implicitly to the method.
So my question is what happens when a method is invoked on a struct ? Is it similar to classes in this aspect?
Note that you can have both member data and methods inside a struct. Also, you can specify the members as private, public and internal. It should be noted that unlike classes, you cannot have field initializers for non-static fields in structs. Hence, statements like the following in a struct are not valid.
Features of C# StructuresStructures can have methods, fields, indexers, properties, operator methods, and events.
The struct (structure) is like a class in C# that is used to store data. However, unlike classes, a struct is a value type. Suppose we want to store the name and age of a person. We can create two variables: name and age and store value.
Basically, a class combines the fields and methods(member function which defines actions) into a single unit. A structure is a collection of variables of different data types under a single unit. It is almost similar to a class because both are user-defined data types and both hold a bunch of different data types.
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
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.
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