时间:2021-05-20
这是C#中一个有趣的现象,也许您从中可以窥见些许CLR在构造类型时的行为,以及JIT编译的触发式编译过程。
看下面一段代码:
复制代码 代码如下:
class Program
{
static void Main()
{
myValueType1 type1 = new myValueType1();
Console.WriteLine(myValueType1.myInt);
Console.WriteLine("**********************");
myValueType2 type2 = new myValueType2();
type2.myInt =23;
Console.WriteLine(type2.myInt);
Console.WriteLine("**********************");
myValueType3 type3 = new myValueType3();
}
}
struct myValueType1
{
static myValueType1()
{
Console.WriteLine("Hello from myValueType1");
// myInt = 111;
}
public static Int32 myInt;
}
struct myValueType2
{
static myValueType2()
{
Console.WriteLine("Hello from myValueType2");
}
public Int32 myInt;
}
struct myValueType3
{
static myValueType3()
{
Console.WriteLine("Hello from myValueType3");
myInt = 333;
}
public static Int32 myInt;
}
这里定义了三个结构:myValueType1,myValueType2,myValueType3。三个结构均带静态构造器,在构造器中都有一句用来输出的的代码。在myValueType1和myValueType3的静态。然后我们在main函数里面分别new 了相应的三个实例。您可以先想想输出的结果应该是怎样的。
事实上您会得到如下的结果:
我们看到虽然三个结构中都有静态构造器,却只有第一个结构的被执行了。事实上,这个有趣的现象也是CLR对性能的考虑,除非类型确实被访问到了,否则永远不会调用到它的类型构造器,这个过程是JIT的。
当执行到第六行代码时,CLR尝试要去myValueType1查找静态字段myInt的值。这个时候,myValueType1才是真正被访问到了。静态构造器被执行,得到相应的输出。
而myValueType2中myInt是个实例成员,访问它的值只关系到实例type2实例。与类型本身没有任何关系,CLR不会执行类型myValueType2的静态构造器。
myValueType3跟myValueType11几乎是一样的,myInt是静态成员,但是在main函数中,myValueType3还是没有被真正访问到,只是利用它构造出了一个虚拟的对象结构,这种对象结构里面所有字段都被赋予一个0值或者null值,所以第二行输出为零
这些性质与JIT编译器都是分不开的。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
C#方法1:实例构造器和类2:实例构造器和结构3:类型构造器4:操作符重载方法5:转换操作符方法6:扩展方法7:部分方法1:实例构造器和类构造器是允许将类型的实
这里直接给出C#类成员一般初始化顺序:子类静态字段子类静态构造子类实例字段父类静态字段父类静态构造父类实例字段父类实例构造子类实例构造为什么说是“一般”初始化顺
在理解var和dynamic关键字之前,让我们先了解一下编程语言的类别。C#中有两类编程语言:静态类型语言类别动态语言类别静态类型语言静态类型语言也被称为强类型
创建类:class后跟类名,其中类名的首字母必须要大写。实例化时,通过new方法实例化。在c#中有构造器,构造器与类同名。在ruby中,构造器为initiali
最近,在与同事进行协同编程时,我们开始讨论在C#中初始化新对象的最佳方法。我一直是使用构造函数实现,尽管他倾向于静态工程方法。这引起了关于每种类型的利弊的大量来