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

发布时间:2020-07-19 01:36:02 作者:yisuowushinian
来源:网络 阅读:1015

目录:

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

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

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

----------------------------------分割线--------------------------------------


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

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

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; }
        //}
    }


当我们只是声明一个类和一个结构体的时候,我们的编译器顺利的编译通过。并且打印出结果如下:

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


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


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

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


结构默认的构造函数(如果没有显式声明)在实例化的时候才会被调用。所以,

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

在内存中是如下的情况:

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


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


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

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

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


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


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

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


这时候,我们再深入到WriteLine()方法中去,源代码,如下:

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


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

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

因为p已经在栈中创建了对象(但是不可用),所以,直接进入else语句。


明显的可以发现IFormattable是一个接口,我们再看IFormattable接口的源码,如下:

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


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

else

 {          

this.WriteLine(value.ToString());    

  }

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

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


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

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


打印结果:

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



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



如果您觉得不错,点击右下角赞一下吧!您的支持,是我写作的动力!

毕业实习交流群:221376964。你也可以关注我的新浪微博进行交流。

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


推荐阅读:
  1. 怎么在python使用OpenCV进行人像分割与合成
  2. 怎么在PostgreSql中重建索引

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

知识 结构体 分割线

上一篇:C#浅谈NET抽象类和接口的区别

下一篇:windows 10 中启用隐藏的Administrator账户

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》