是否在C#中调用空构造函数?

时间:2015-06-01 09:25:52

标签: c# constructor

给出一个空构造函数,例如:

internal C()
{
}

是否需要创建对象?它应该只包含一个返回操作,所以理论上它可以被丢弃,对吧?

注意: me 很明显,对于每个类,都存在一个隐式构造函数。然而,这个问题的意图是;如果CLR调用只有return操作的构造函数。

5 个答案:

答案 0 :(得分:5)

构造函数始终在对象实例化时被调用,即使它是无参数且为空的。如果您不编写任何构造函数,编译器会为您隐式生成默认构造函数。

这是为了让您可以稍后在上编写构造函数,而无需重新编译任何调用代码。

对象实例化总是因为这个原因调用构造函数,除了像FormatterServices.GetUninitializedObject之类的边缘情况,这是我知道实例化对象而不调用构造函数的唯一方法(它用于序列化目的)

顺便说一句,newobj IL操作码(用于实例化新对象)显式地将构造函数作为输入参数:

  

newobj指令创建新对象或值类型的新实例。 Ctor 是一个元数据标记(必须标记为构造函数的methodref或methoddef),它指示要调用的构造函数的名称,类和签名。

     

newobj指令分配与 ctor 关联的类的新实例,并将新实例中的所有字段初始化为0(正确类型)或null适当的参考。然后,它使用给定的参数以及新创建的实例调用构造函数 ctor 。调用构造函数后,现在初始化的对象引用(类型O)将被压入堆栈。

因此,要创建的类型实际上是由构造函数标识为,而不是类型标记本身,这使得构造函数成为必需的。

由于您想知道JIT的作用,以下是在发布模式下反汇编以下行(SomeClass是一个具有空默认构造函数的类):

var inst = new SomeClass();

64:

000007FE95A30093  in          al,dx  
000007FE95A30094  and         byte ptr [rax-73h],cl  
000007FE95A30097  or          eax,0FFEE4014h  
000007FE95A3009C  call        000007FEF5062400  
000007FE95A300A1  mov         rbx,rax  
000007FE95A300A4  call        000007FEEC977A00  

86:

00320050  push        ebp  
00320051  mov         ebp,esp  
00320053  push        esi  
00320054  mov         ecx,28380Ch  
00320059  call        002720D4  
0032005E  mov         esi,eax  
00320060  call        72EA2578  
00320065  mov         ecx,eax  
00320067  mov         eax,dword ptr [ecx]  
00320069  mov         eax,dword ptr [eax+2Ch]  
0032006C  call        dword ptr [eax+1Ch]  

好吧,我对汇编代码不太熟悉,但x64版本执行两次调用。我想第一个是分配,第二个是构造函数调用,但我不确定(VS因为某些原因不允许我去这些地址)。 x86代码中的第三个(间接)call对我来说是一个惊喜,我不知道它是为了什么。

答案 1 :(得分:1)

不,构造函数应该被丢弃,因为它似乎是该类的作者只是想从它的声明程序集中实例化它(通过将构造函数标记为{{ 1}})。

答案 2 :(得分:0)

不,如果您不提供,将隐式调用默认构造函数。创建对象时,将传递构造函数,nextobjpointer指向当前对象引用。

答案 3 :(得分:0)

是的,它会在每个对象创建时被调用,因为它是默认构造函数。如果您没有任何其他参数化构造函数,则可以省略它,但如果您使用其他构造函数,则需要指定默认构造函数。有关详细信息,请参阅this

答案 4 :(得分:0)

如果你编写一个构造函数,那没关系。每次声明任何类的对象都会撤消构造函数。

现在您可以明确地使用此构造函数来完成一些工作。

或者您可以将其留空或甚至不要在课堂上写下来。

保持空白而不是编写构造函数是完全相似的。