接下来我们简单的说明一下这一节说明的构造器的几个准则:
- 为实例的数据字段分配内存
- 初始化附加字段(类型对象指针和同步块索引)
- 调用构造器进行初始化
- 当构造实例时先调用基类
- 构造器中一般不调用虚方法
首先给大家解释一下为什么会代码膨胀:
using System;
namespace clr8_demo1
{
internal sealed class SomeType
{
private Int32 m_x = 5;
public static void Main()
{ }
}
}
对于这段非常简单的代码,我们用查看.ctor的IL:我们可以清楚的看到在.ctor的IL代码中5存储到m_x中,然后调用基类的构造器。
懂了上面那段话的意思,我们来看个更复杂的代码(其实一点都不复杂):
using System;
namespace clr8_demo1
{
internal sealed class SomeType
{
private Int32 m_x = 5;
private String m_s = "Hi there";
private Double m_d = 3.14159;
private Byte m_b;
public SomeType() { }
public SomeType(Int32 x) { }
public SomeType(String s) { m_d = 10; }
public static void Main()
{ }
}
}
对于这段代码我们在看构造器的IL之前应该可以想到在三个构造器中都分别对上面的几句简单的代码进行了初始化操作,这里就是关键,我们随便很简单的几句代码,在后台却进行了三次初始化操作,这就是我们说的代码膨胀:(我们来看下三个IL代码)
这里面分别对m_x,m_s,m_d都进行了存储
这里面同样分别对m_x,m_s,m_d都进行了存储
这里面同样分别对m_x,m_s,m_d都进行了存储
通过这三段IL代码验证了我们之前的猜想,那们该怎么解决呢?通过this指针显示调用构造器
再看一段代码:
using System;
namespace clr8_demo1
{
internal sealed class SomeType
{
private Int32 m_x;
private String m_s;
private Double m_d;
private Byte m_b;
public SomeType()
{
m_x = 5;
m_s = "Hi there";
m_d = 3.14159;
m_b = 0xff;
}
public SomeType(Int32 x)
: this()
{
m_x = x;
}
public SomeType(String s)
: this()
{
m_s = s;
}
public SomeType(Int32 x, String s)
: this()
{
m_x = x;
m_s = s;
}
public static void Main()
{ }
}
}
我们再来分析一下IL代码:
在.ctor中还依然一样存储在各个字段中,但是我们看一下剩下三个IL代码可以发现一些惊喜(如下):
从上面三段IL代码可以看到在后台任务减轻,目的达到。
联系客服