代码改变世界

解读经典《C#高级编程》第七版 Page20-32.核心C#.Chapter2

2018-12-25 13:20  圣殿骑士18  阅读(421)  评论(0编辑  收藏  举报

前言

 

讲到核心C#的语法,其实很难讲,因为大部分是基础知识。如果只讲入门的基础知识,那细节又多,意义也不大。我们就不讲一般性的内容,而是找一些有趣的点,展开讲讲。

 

01

Hello World

 

Hello World

一般开始编程的开头,都是写一个Hello World程序,这本书也是不能免俗。我们发现,Hello World基本都是用控制台(Console)程序写的。为什么是控制台程序?控制台程序只是一个测试用,学习用的框架吗?并不是这样。了解Java程序的同学可能都会发现,很多Java程序运行起来都是一个黑乎乎的控制台程序,年代越早这种情况越普遍。现在比较少了,毕竟体验不好,逐渐用UI或者系统Service代替。但控制台还是很强大的,在Windows面世之前,所有的程序都是控制台程序,比如用Foxpro开发的财务记账系统。而现在这种控制台程序也很多,Java方面更多,因为Java要跨平台,就相对的重功能轻UI。现在做前端开发,标配都会有不少叫XXX-CLI的控制台工具,用于生成脚手架代码。

程序入口

为什么控制台程序入口是Main()方法?我们知道,程序都需要入口,而不同类型的程序,入口都不同,比如控制台、Winform程序是Main()方法,而asp.net程序是Application_Start()方法。

编译器

Csc.exe是什么?它是C#的命令行编译器程序,我们可以将Visual Studio(以下简称VS)理解为就是集成了一大堆包括csc.exe这类控制台程序而形成的一个大工具系统。类同Java,Java的编译器程序是javac.exe,java编译完成后的代码文件是*.class文件,运行*.class文件需要另外一个控制台程序java.exe,即用命令行执行java.exe xxx.class。而.Net有所不同,csc.exe编译完成后是一个可执行的exe程序(或者类库*.dll),微软的Windows革了控制台的命,所以我们用微软的工具时天然的会感觉到去控制台化,比如VS,体验好到.Net程序员不愿意去做Java开发。

Static

Main()方法为什么是静态的(static)?我们会发现,不管是Java,C#,Main方法都是静态方法,这给初学者其实带来一定的迷惑性。我想,不能说程序入口必须用静态方法,因为“在比特世界里,没有代码实现不了的事情”,而是因为使用静态方法是“最好的入口设计”。我们用对象化的人类语言来模拟程序的启动,它应该是这样描述:

程序.启动();

用C#控制台程序代码实现的就是:

Program.Main();

我们会发现,这样一来Main()就应该是一个Program类的静态方法。那为什么不先var p = new Programm(),在调用p.Main()?因为程序启动只应该是为了“启动”,而不是为了new一个对象,new一个对象可能会带来副作用,比如new一个对象会附带着对对象的初始化,而对象的初始化又带着一堆构造器代码,而这并不是程序“启动”该做的事情。因此静态的Main()方法是最好的设计。

 

02

变量

 

变量定义

C#的变量定义,使用前必须初始化。这是学Java的,为了程序的强壮性和安全性。 但同时,这句话是有前提的,是“方法中的变量,必须初始化后才能使用。”而类定义中的字段呢?并不需要。为什么??其实很简单,我们设计一门语言,它的本质是工具,是为了方便开发者,而不是给开发者添堵来的。这句话作为第一性原理,可以应用到理解语言的方方面面。假如你设计了一个类,还要在类的构造方法里逐个初始化类的所有字段,你是不是要发疯?所以类在new的时候,它的字段会自动被赋予“类型的默认值”。比如int就是0,string就是null。取得一个类型的默认值,我们可以用比如:

var value = default(int);

这样写在实际开发中几乎用不到,但等到我们后面再定义泛型类的时候,defalt(T),可能是必须用到的,用来取得一个类型的默认值。

而为什么方法中的变量会必须有默认值呢?我想语言的设计者,应该是认为:“你写一段代码,要定义一个变量,就应该是知道应该给变量初始化什么值,才能使这段代码运行的最安全和保持健壮”。

类型推断

C#定义变量时,可以让编译器进行类型推断,而不明确声明类型,比如:

var endDateTemp = endDate.Value.AddDays(1);

类型推断var是个好东西。作为一个完美主义,我初学C#时,把握不好该不该用var?用var明显不好的一点是,阅读性不够好,你不知道定义的这个类型是什么类型,在VS中,你需要用鼠标移到变量上,才能看到这个变量的类型是什么。所以曾经有一段时间,我强烈的拒绝用var,变量定义类型必须手写。然鹅我现在已经定义变量几乎都用var了。因为要使用太多的类,在现代强类型开发的风潮之下,类的名称又往往很长,手写将大大影响开发效率。实际上,写这么多var,并没有给我带来之前我担心的困扰,反而写的很顺,很爽。但作为完美主义的我,还是坚持在某些情况下,不使用var,因为我坚信:“任何好东西,都是不能滥用的”。所以,“在不影响开发效率的前提下,不使用var”,就是我的一直秉承的原则。我一般原则是:

  1. 如果接收一个方法的返回值,我一般用var
  2. 定义并new一个对象,我一般不用var;定义基础类型和string,我基本不用var

变量作用域

作用域不详述。不过我分享一个我使用花括号来避免变量作用域冲突的小技巧,有点意思。

常量 const

常量不详述。不过有句话很有意思,“常量总是静态的”,但这不仅仅是理解为定义常量时不需要使用static,而是它具有static变量定义的本质,就是“数据只有一份”。所以我们可以畅想一下,如果定义了一个类User,这个类中定义了一个int常量字段,那么不管这个类创建了1个还是100个,它们使用的这个常量始终只有一份,存储在堆栈中。

 

下一篇,讲预定义类型。

 

觉得文章有意义的话,请动动手指,分享给朋友一起来共同学习进步。

 

欢迎关注本人微信公众号,更及时的关注最新文章(每周三篇原创文章,以及多篇专题文章):

附文:

C# 翻身?微软重写开源的 C# 编译器!

C#中变量的作用域

 

上一篇:解读经典-《C#高级编程》第七版-Chapter1-.Net体系结构-Page13-20