结构上的方法调用?

Sea*_*ock 28 .net c# struct

当我们在对象上调用方法时,对象的引用将隐式传递给方法.

所以我的问题是在结构上调用方法时会发生什么?它与这方面的类似吗?

Flo*_*her 27

根据CIL规范,this指针通过引用/作为托管指针传递.正如Binary Worrier所假设的那样,这是一个CIL功能.

应该对类的实例和虚方法进行编码,以期望对该类的实例的引用作为该指针. 相比之下,值类型的实例和虚方法应编码为期望托管指针(请参阅分区I)到值类型的未装箱实例. 当盒装值类型作为this指针传递给虚拟方法时,CLI应将盒装值类型转换为指向未装箱值类型的托管指针,该方法的实现由未装箱的值类型提供.

因此,从高级角度来看,对引用类型(类)的实例方法的调用如下所示:

MyClass myClass = MyClass_Constructor();

MyClass_MyInstanceMethod(myClass, myFirstParameter);
//                       ^
//                       The "this" argument
Run Code Online (Sandbox Code Playgroud)

并调用值类型(struct)的实例方法,如下所示:

MyStruct myStruct = MyStruct_Constructor();

MyStruct_MyInstanceMethod(ref myStruct, myFirstParameter);
//                        ^
//                        The "this" argument
Run Code Online (Sandbox Code Playgroud)

  • +1。重要的是该值不会被装箱,这可以防止性能下降。 (3认同)

Eri*_*ert 22

弗洛里安是对的; 在我们讨论这个话题时,还有一些细节:

当我们在对象上调用方法时,对象的引用将隐式传递给方法.

正确.考虑这个问题的一种方法是调用方法:

class C
{
    int y;
    public void M(int x) 
    { 
        Console.WriteLine(x + y); 
    }
}
...
C c = new C();
c.M(10);
Run Code Online (Sandbox Code Playgroud)

实际上是一样的

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);
Run Code Online (Sandbox Code Playgroud)

也就是说,每个实例方法都有一个隐藏的"this"参数,并且该方法"真的"是静态的.

所以我的问题是在结构上调用方法时会发生什么?它与这方面的类似吗?

是.传递的内容是包含结构的变量的别名,而不是对实例的引用.这就是struct方法可以改变结构的方式.(当然,改变结构是一种不好的做法,但有时是必要的.)

struct S
{
    int y;
    public void M(int x) 
    { 
        Console.WriteLine(x + y); 
    }
}
...
S s = new S();
s.M(10);
Run Code Online (Sandbox Code Playgroud)

在逻辑上是相同的

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);
Run Code Online (Sandbox Code Playgroud)

然后出现一个有趣的问题:如果"接收器"不是变量怎么办?(*)您只能将ref作为变量.假设你有:

GetAnS().M(10); 
Run Code Online (Sandbox Code Playgroud)

??? 那么会发生什么?

我们为你做一个变量.那变成了

S temporary = GetAnS();
temporary.M(10);
Run Code Online (Sandbox Code Playgroud)

现在接收器是一个变量,所以我们可以将"隐藏此参数"作为它的别名.

(*)这里还有其他一些有趣的案例,比如结构是可变的但变量是只读的,依此类推.

  • 我知道如何找出答案.尝试两种方式,并通过您的效率经验衡量看哪哪种更有效. (2认同)