目录:

【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。你也可以关注我的新浪微博进行交流。

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

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

  1. C#中的线程(上)-入门 分类: C# 线程 2015-03-09 10:56 53人阅读 评论(0) 收藏

    1.     概述与概念 C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行.一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为"主线 ...

  2. iOS中UITextField 使用全面解析 分类: ios技术 2015-04-10 14:37 153人阅读 评论(0) 收藏

    //初始化textfield并设置位置及大小   UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 13 ...

  3. OC基础知识总结 分类: ios学习 OC 2015-06-26 17:58 58人阅读 评论(0) 收藏

    //OC: Objective-C, 面向对象的C语言 //OC与C的区别 //1.OC是C的超集, C语言的所有语法都可以在OC中使用 //2.OC是面向对象 //3.OC是一门运行时语言 //4. ...

  4. 解决ORA-29857:表空间中存在域索引和/或次级对象 & ORA-01940:无法删除当前连接的用户问题 分类: oracle sde 2015-07-30 20:13 8人阅读 评论(0) 收藏

    今天ArcGIS的SDE发生了一点小故障,导致系统表丢失,所以需要重建一下SDE数据库,在删除SDE用户和所在的表空间过程中遇到下面两个ORA错误,解决方法如下: 1)删除表空间时报错:ORA-298 ...

  5. VS2010中使用命令行参数 分类: c/c++ 2014-07-11 22:24 634人阅读 评论(0) 收藏

    在Linux下编程习惯了使用命令行参数,故使用VS2010时也尝试了一下. 新建项目,c++编写程序如下: #include<iostream> #include<fstream&g ...

  6. Java中的日期操作 分类: B1_JAVA 2015-02-16 17:55 6014人阅读 评论(0) 收藏

    在日志中常用的记录当前时间及程序运行时长的方法: public void inject(Path urlDir) throws Exception { SimpleDateFormat sdf = n ...

  7. C/C++中const的用法 分类: C/C++ 2015-07-05 00:43 85人阅读 评论(0) 收藏

    const是C语言的关键字,经C++进行扩充,变得功能强大,用法复杂.const用于定义一个常变量(只读变量),当const与指针,引用,函数等结合起来使用时,情况会变得复杂的多.下面将从五个方面总结 ...

  8. 认识C++中的临时对象temporary object 分类: C/C++ 2015-05-11 23:20 137人阅读 评论(0) 收藏

    C++中临时对象又称无名对象.临时对象主要出现在如下场景. 1.建立一个没有命名的非堆(non-heap)对象,也就是无名对象时,会产生临时对象. Integer inte= Integer(5); ...

  9. ubuntu中安装jdk 分类: java 学习笔记 linux ubuntu 2015-07-06 17:49 74人阅读 评论(0) 收藏

    参考文献:ubuntu 13.04 安装 JDK 先去oracle官网下载jdk,这一段我就不赘述了. 下载好之后先解压,解压方式参见 linux常用的压缩与解压缩命令 ,解压之后,将文件剪贴至/us ...

随机推荐

  1. 记录一次shell里局部变量的问题

    一:起因是这样的,自己今天面试被问到怎么读取某文件夹下所有的文件的每一行的数值的总和:其中文件中数值在每一行里的格式为num|,如33|,因此我第一想到的是通过cut -d\| f1 file来获取每 ...

  2. python将字典中的数据保存到文件中

    d = {'a':'aaa','b':'bbb'}s = str(d)f = open('dict.txt','w')f.writelines(s)f.close()

  3. Memcached 应用场景

    1. 把java对象序列化成base64 存入缓存,不同平台可以反序列化. 2. 通过key去重复 3. 保存一些信息,供所有平台使用

  4. 城市边界线预测(根据灯光指数)(PUL)

    1.EXEALL.m function EXEALL(FilePath, FileName)%执行所有流程% FilePath: 文件夹所在路径% FileName: 文件夹名称 FullPath = ...

  5. (连通图 ) Redundant Paths --POJ --3177

    链接: http://poj.org/problem?id=3177 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82833#probl ...

  6. windows7,windows8 64位系统 IIS7.0配置.net网站时报错:未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。

    背景: 在64位的操作系统中, IIS7.0配置.net网站时报错:未能加载文件或程序集“XXX”或它的某一个依赖项.试图加载格式不正确的程序. 解决办法: 把iis 对应的应用程序池 --高级设置- ...

  7. jquery使用ajax报错[Uncaught SyntaxError: Unexpected token :]

    $.post('/ajax/validate.do',{"id": id},function(ret){ //ret }); 返回值明明是json,格式也是正确的,却解析不成功,在 ...

  8. 曲演杂坛--Update的小测试

    今天偶然想起一个UPDATE相关的小问题,正常情况下,如果我们将UPDATE改写成与之对应的SELECT语句,其SELECT查询结果应与UPDATE的目标表存在一对一的关系,例如: 对于UPDATE语 ...

  9. 浏览器拦截跨域请求处理方法(同源策略不允许读取XXX上的远程资源)

    直接了当了说,解决此类问题,最直接的方法就是,就是给被请求的服务器,添加HTTP头响应头,这里提供两种添加HTTP头的方法: 第一种,就是在程序中添加HTTP头: Response.AddHeader ...

  10. 蚂蚁男孩.缓存组件(Framework.Mayiboy.Caching)

    它能做什么? 主要是用来方便使用缓存而诞生,该组件封装了RunTimeCache.Memcached.Redis的使用,通过简单配置就能高效快速使用起来. 使用说明 一.    下载源码,自己手动编译 ...