前言

讲到核心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

解读经典《C#高级编程》第七版 Page20-32.核心C#.Chapter2的更多相关文章

  1. c#高级编程第七版 学习笔记 第一章 .NET体系结构

    第一章      .NET体系结构 本章内容: 编译和运行面向.NET的代码 Microsoft中间语言(Microsoft Intermediate Language,MSIL或简称IL)的优点 值 ...

  2. c#高级编程第七版 学习笔记 第二章 核心c#

    第二章 核心C# 本章内容: 声明变量 变量的初始化和作用域 C#的预定义数据类型 在c#程序中使用条件语句.循环和跳转语句执行流 枚举 名称空间 Main()方法 基本的命令行c#编译器选项 使用S ...

  3. c#高级编程第七版 学习笔记 第三章 对象和类型

    第三章 对象和类型 本章的内容: 类和结构的区别 类成员 按值和按引用传送参数 方法重载 构造函数和静态构造函数 只读字段 部分类 静态类 Object类,其他类型都从该类派生而来 3.1 类和结构 ...

  4. C#高级编程第9版 第二章 核心C# 读后笔记

    System命名空间包含了最常用的.NET类型.对应前面第一章的.NET基类.可以这样理解:.NET类提供了大部分的功能,而C#语言本身是提供了规则. pseudo-code,哈哈,秀逗code.伪代 ...

  5. ASP.NET MVC 4高级编程(第4版)

    <ASP.NET MVC 4高级编程(第4版)> 基本信息 作者: (美)Jon Galloway    Phil Haack    Brad Wilson    K. Scott All ...

  6. 《UNIX环境高级编程(第3版)》

    <UNIX环境高级编程(第3版)> 基本信息 原书名:Advanced Programming in the UNIX Environment (3rd Edition) (Addison ...

  7. 【转】apue《UNIX环境高级编程第三版》第一章答案详解

    原文网址:http://blog.csdn.net/hubbybob1/article/details/40859835 大家好,从这周开始学习apue<UNIX环境高级编程第三版>,在此 ...

  8. Linux - Unix环境高级编程(第三版) 代码编译

    Unix环境高级编程(第三版) 代码编译 本文地址:http://blog.csdn.net/caroline_wendy 时间:2014.10.2 1. 下载代码:http://www.apuebo ...

  9. Unix环境高级编程第三版中实例代码如何在自己的linux上运行的问题

    学习Linux已经有2个月了,最近被期末考试把进度耽误了,前几天把Unix环境高级编程看了两章,感觉对Linux的整体有了一些思路,今天尝试着对第一章涉及到的一个简单的交互式shell编译运行一下,结 ...

  10. C#高级编程笔记之第二章:核心C#

    变量的初始化和作用域 C#的预定义数据类型 流控制 枚举 名称空间 预处理命令 C#编程的推荐规则和约定 变量的初始化和作用域 初始化 C#有两个方法可以一确保变量在使用前进行了初始化: 变量是字段, ...

随机推荐

  1. submit与execute区别

    1.可以接受的任务类型 submit: execute: 可以看出: execute只能接受Runnable类型的任务 submit不管是Runnable还是Callable类型的任务都可以接受,但是 ...

  2. 启动eclipse could not create the java Vittual Machine

    查询并几种方法: 1.都说是 eclipse.ini  环境初始文件的内存问题,续增大堆内存大小,具体配置如,如果找不到问题所在可以试试(该方法是确定环境变量没问题下试行) -Xms64m-Xmx25 ...

  3. 可遇不可求的Question之MySql4.0前版本不支持union与批量SQL提交

    批量SQL提交 参考 21.2.6. Connector/NET Connection String Options Reference . Allow Batch true When true, m ...

  4. linux sshd 登录不需要密码

    ssh 安全外壳协议 协议22 linux 默认放行了 22 号接口 ssh 默认安装 自行安装 应该是 openssh-server ssh命令是 openssh ssh-keygen 生成密钥 生 ...

  5. OC内存管理、非ARC机制、MRR机制

    在Xcode里面,默认为ARC(auto reference counting),也就是自动内存管理机制,在这里我们要了解的是内存管理,肯定是不能让系统帮我们管理内存,我们需要将ARC关闭,首先在左边 ...

  6. Codeforces831B Keyboard Layouts

    B. Keyboard Layouts time limit per test 1 second memory limit per test 256 megabytes input standard ...

  7. java与eclipse的工作小结

    1.Eclipse 的启动画面 A.加启动参数.如: eclipse.exe -showsplash C:/splash.bmp 更多可参考:http://www.cnblogs.com/sharew ...

  8. MySQL--MHA原理

    ##==============================================================##MHA(Master High Availability)是一种My ...

  9. Java开发面试题,3年工作经验的Java程序员面试经

    一.Java基础部分 1.使用length属性获取数组长度,public.private.protected.friendly区别 2.Collection和Collections区别 3.Strin ...

  10. 每天学点SpringCloud(十三):SpringCloud-Stream整合RabbitMQ

    我们知道,当微服务越来越来多的时候,仅仅是feign的http调用方式已经满足不了我们的使用场景了.这个时候系统就需要接入消息中间件了.相比较于传统的Spring项目.SpringBoot项目使用消息 ...