Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method invocation on a struct?

Tags:

c#

.net

struct

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?

like image 579
Searock Avatar asked May 05 '11 09:05

Searock


People also ask

Can we use methods in struct?

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.

Can a struct have a method in C#?

Features of C# StructuresStructures can have methods, fields, indexers, properties, operator methods, and events.

What is struct in C# with example?

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.

What is the difference between struct and class in C#?

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.


2 Answers

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 
like image 94
Florian Greinacher Avatar answered Oct 11 '22 12:10

Florian Greinacher


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.

like image 20
Eric Lippert Avatar answered Oct 11 '22 12:10

Eric Lippert