【C#小知识】C#中一些易混淆概念总结(四)---------解析Console.WriteLine()

目录:html

【C#小知识】C#中一些易混淆概念总结函数

【C#小知识】C#中一些易混淆概念总结(二)

【C#小知识】C#中一些易混淆概念总结(三)

----------------------------------分割线--------------------------------------工具

 

这几天在温习结构体和类的时候遇到一个问题。发现一个奇怪的现象,一直找不到合理的答案。可是今天终于找到了合理的答案,因此拿来和你们分享一下。post

咱们首先来看下面的一段代码:this

class Program { static void Main(string[] args) {  Point p; Console.WriteLine(p); Point p1 = new Point(); Console.WriteLine(p1); Console.ReadKey(); } } //定义结构
    struct Point { ////定义时赋初始值,编译器会报错
        //private int x; //public Point() //{ }
 } class Person { //在类中咱们能够为属性赋初始值 //private int nAge = 5; //public int NAge //{ // get { return nAge; } // set { nAge = value; } //}
 }

 

当咱们只是声明一个类和一个结构体的时候,咱们的编译器顺利的编译经过。而且打印出结果以下:url

 

为何咱们没有在结构和类中作任何操做,却能够打印出结果,且是“命名空间+"."+数据类型”呢?spa

 

首先我查阅了MSDN的关于结构(struct)的官方文档(地址点击这里),有以下的一段话:code

 

结构默认的构造函数(若是没有显式声明)在实例化的时候才会被调用。因此,   orm

        //结构的实例化能够不使用NEW关键字,只是将p加载到栈空间中,可是对象不可用,这里没有调用默认的构造函数
 Point p2; Console.WriteLine(p2);  Console.WriteLine(p2); Console.ReadKey();

在内存中是以下的状况:htm

 

此时在栈中已经存在了p这个对象,可是不可用。

 

那么为何会打印出“命名空间+"."+数据类型”的结果呢?

咱们先看一下VS编译后的中间代码,即Msil,详细解释在图中给出:

 

有中间语言代码,咱们能够知道,最后调用的是Console.WriteLine(Object)方法

 

这时候就要深刻的研究一下Console类了,用反编译工具.NET Reflector查看Console类,由于在上面的代码中,传进.WriteLine()方法的是一个类,因此,咱们要查看它的的(object value)方法,以下图:

 

这时候,咱们再深刻到WriteLine()方法中去,源代码,以下:

 

再看Out.WriteLine()的源代码:

由于p已经在栈中建立了对象(可是不可用),因此,直接进入else语句。

 

明显的能够发现IFormattable是一个接口,咱们再看IFormattable接口的源码,以下:

 

显然咱们的Point 结构没有实现一个ToString()方法,不存在继承关系,因此会转化失败,返回一个null值,又进入下一个else语句

else { this.WriteLine(value.ToString()); }

这时候最重要的就要来了,咱们看到value值被转换为字符串输出了,在看ToString()源代码,以下:

 

很明显的发现,是获取该对象的数据类型而且转化为字符串输出。以下代码:

        Point p; //打印出p的数据类型
 Console.WriteLine(p.GetType()); Point p2; Console.WriteLine(p2); //使用NEW实例化了对像,调用了默认的构造函数
            Point p1 = new Point(); Console.WriteLine(p1); Console.ReadKey();

 

打印结果:

 

 

这样对结构和类的了解有没有更深刻的了解呢?

相关文章
相关标签/搜索