• 【C#小知识】C#中一些易混淆概念总结(四)---------解析Console.WriteLine() 分类: C# 2014-02-05 17:18 1060人阅读 评论(0) 收藏


    目录:

    【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; }
            //}
    
        }
    复制代码

     

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

     

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

     

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

     

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

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

    在内存中是如下的情况:

     

    此时在栈中已经存在了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();
    复制代码

     

    打印结果:

     

     

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




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

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Python学习笔记_从CSV读取数据写入Excel文件中
    Python学习笔记_Python向Excel写入数据
    Python学习笔记_一个Tkinter示例,使用FileDialog
    Python学习笔记_我的参考网址
    Python读取CSV文件,报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0xa7 in position 727: illegal multibyte sequence
    Python读取CSV文件
    JS写的多级联select,如何取值
    c#常用的Datable转换为json,以及json转换为DataTable操作方法
    C# 读写App.config
    一个简单的存储过程使用事务的例子
  • 原文地址:https://www.cnblogs.com/yisuowushinian/p/4715617.html
Copyright © 2020-2023  润新知