Skip to content

第 02 课:编程语言是什么,为什么这么多

更新: 6/16/2026 字数: 0 字 时长: 0 分钟

为什么学这个

上一课我们说了计算机是一个听话的机器,给它指令它就干活。今天要回答两个问题:第一,我们怎么给计算机下指令;第二,为什么市面上有几百种编程语言,而不是一种统一的"计算机语"。

学完这课你不会写任何代码,但你会理解 C# 在整个编程世界里的位置。这个地图很重要——很多人学了很久编程,还是不知道为什么自己在学 C# 而不是 Python 或者 Java,也不知道换一门语言到底要付出多大代价。搞清楚这些问题,后面学语法的时候才不会迷茫。

编程语言本质上是什么

编程语言是人写给计算机看的"指令说明书"。它的本质很简单:人类用自己能读懂的符号写出一套逻辑,然后通过一个翻译工具,把这份说明书转成计算机原生能执行的机器码。

计算机的原生"语言"是机器码。机器码长成什么样呢?一堆 0 和 1:

10110000 01100001

上面这串东西,在 x86 架构的 CPU 上,可能表示"把数字 97 加载到某个寄存器里"。但这串东西对人来说几乎是不可读的。一百个指令排在一起,谁也分不清哪个是哪个。

于是人们发明了汇编语言。汇编用助记符代替数字,让指令稍微好读一点:

MOV AL, 61h

这一行做的事和上面那串 0 和 1 完全一样。"MOV"是 move 的缩写,"AL"是一个寄存器名字,"61h"是十六进制的 97。汇编比机器码好读,但它依然很底层。你写一行汇编,对应 CPU 做一件事。要写一个简单的计算器,可能需要上千行汇编代码。

这就引出了更高级的编程语言。高级语言的思路是:让一行代码能做更多的事,让语法更像人类的思维。比如在 C# 里,你想把两个数加起来:

csharp
int result = 3 + 5;

这一行代码经过编译器处理之后,会变成多条 CPU 指令。你不用管寄存器怎么分配、内存怎么寻址,只需要告诉编译器"我要做加法",剩下的它搞定。

所以编程语言就是一个"距离 CPU 有多远"的光谱:机器码紧贴 CPU,汇编近一点,C 语言再近一点,C# 和 Python 这类就离得很远了。离得越远,你写起来越舒服,但运行效率往往越低——因为中间多了一层翻译。

翻译的两种方式:编译 vs 解释

所有高级编程语言要变成机器码,只有两条路:编译或者解释。

编译的意思是:在你运行程序之前,先用一个叫"编译器"的工具,把整个源代码一次性翻译成机器码,生成一个可执行文件(Windows 上的 .exe 就是一种)。以后你双击这个 .exe,CPU 直接执行机器码,不需要再翻译。C#、C++、Rust、Go 都是编译型语言。

解释的意思是:不提前翻译,而是在运行的时候,由一个叫"解释器"的程序一行一行地读你的源代码,读一行执行一行。你从来没有一个独立的 .exe 文件,要运行就必须有解释器在场。Python、JavaScript、Ruby 是解释型语言的典型代表。

编译的好处是快——程序跑起来因为已经是机器码了,没有翻译过程拖后腿。缺点是你每次改了代码都要重新编译。解释的好处是灵活——改一行代码立刻就能跑,不用等编译。缺点是每运行一次解释器都在后台做翻译工作,整体比编译型慢。

C# 走的路其实介于两者之间。C# 的编译器(Roslyn)会把源代码编译成一种叫 IL(Intermediate Language,中间语言)的东西,而不是直接编译成机器码。程序运行的时候,.NET 运行时里的 JIT(Just-In-Time)编译器再把 IL 实时翻译成机器码。这个设计让 C# 既能跨平台(同一份 IL 可以在 Windows、Linux、macOS 上运行),又有接近原生编译的性能。

mermaid
flowchart LR
    A[源代码 .cs] -->|C# 编译器 Roslyn| B[IL 中间语言 .dll/.exe]
    B -->|.NET JIT 编译器| C[机器码 x86/x64/ARM]
    C -->|CPU 执行| D[程序运行]

编程语言的核心组成部分

不管什么编程语言,语法差别再大,它们都有几个共同的底层构件:

语法(Syntax):规定了代码怎么写才合法。比如 C# 里每条语句必须以分号结尾,Python 可以不写分号但是必须用缩进来表示代码块的层级。语法就像一种语言的拼写和标点规则。

数据类型(Data Types):数据有不同的格式。整数、小数、文本、布尔值(真/假)。每种语言支持的基本类型大同小异,但命名和精度可能不一样。C# 的 int 是 32 位整数,double 是 64 位浮点数。Java 里也有 intdouble,完全一样。Python 里没有显式的类型声明,但你用的数字本质上还是整数和浮点数。

变量(Variables):给数据起个名字,方便后面反复用。就像数学里的 x 和 y,但在编程里你可以给变量起有意义的名字,比如 userAge 或者 filePath

控制流(Control Flow):决定了代码执行的顺序。最基本的是从上到下顺序执行;分支结构(if/else)根据条件决定走哪条路;循环结构(for/while)让一段代码反复执行。

函数/方法(Functions/Methods):把一段可以复用的代码打包成一个单元,起个名字。以后要执行这段逻辑,直接"调用"这个名字就行,不用把代码再写一遍。

输入/输出(I/O):程序总得和外界打交道。读文件、写文件、网络请求、显示文字到屏幕上、接收键盘输入,这些都属于 I/O。

你学任何一门新语言,本质上就是在学这六个东西在那一门语言里是怎么写的。语法规则不同、类型名字不同,但底层概念完全相通。所以有经验的程序员学一门新语言通常能在一两周内上手——因为他已经理解了"循环是什么",只需要知道这门语言的循环怎么写而已。

为什么有几百种编程语言

这个问题问的其实是:一种语言不够用吗?

答案是:不够。因为"写程序"这件事覆盖的场景太广了。写一个网页、写一个操作系统、写一个机器学习模型、写一个嵌入式设备上的温控程序——这些任务的需求完全不同,没有一种语言可以同时满足所有场景。

具体来说,不同语言的分化主要来自以下原因:

执行效率 vs 开发效率的权衡。C 和 C++ 离硬件很近,程序员可以精细控制内存分配,做出来的程序跑得极快。代价是写起来很累——你得自己管理内存的申请和释放,一个不小心就会导致程序崩溃。Python 和 JavaScript 让你用很少的代码完成复杂逻辑,内存管理全自动。代价是运行速度比 C 慢几十倍甚至上百倍。不同的项目对速度的容忍度不一样,所以不同的语言有各自的生存空间。

领域专用性。有些语言是为特定领域设计的。SQL 专门用来操作数据库,你用 SQL 是写不出一个桌面软件界面的——它压根没有"窗口"这个概念。MATLAB 和 R 面向科学计算和统计分析,内置了大量数学函数,用它们做矩阵运算比用 C# 方便得多。HTML 和 CSS 用来描述网页的结构和样式,它们不是通用编程语言,但在自己的领域里不可或缺。

厂商和平台的绑定。苹果的生态推崇 Swift 写 iOS/macOS 应用,谷歌的 Android 生态绑定 Kotlin 和 Java。微软的 Windows 桌面生态长期绑定 C# 和 .NET。这不是说技术上不能用别的语言做,而是厂商提供了最好的工具链和 API 支持,开发者在那个平台上用"亲儿子"语言会省很多麻烦。

历史遗产和社区效应。一门语言一旦积累了海量的库和框架,后来的开发者即使觉得这门语言有些地方不好,也仍然会选它——因为有现成的工具用,不用自己从头造轮子。COBOL 这门 1959 年出生的语言,到今天还在很多银行和政府的核心系统里运行。不是因为它好,而是因为改写整个系统的成本太高了。

学术探索。编程语言的设计本身也是一个研究领域。Haskell 和 Rust 引入了一些新的类型系统理念,这些东西先是在学术界验证,然后逐渐被工业界吸收。Rust 的"所有权"系统解决了 C++ 内存管理的一大痛点,它不是凭空产生的,而是对几十年内存安全研究的一次工程化落地。

下面的图概括了常见语言的定位:

mermaid
quadrantChart
    title 编程语言分布图
    x-axis "低性能" --> "高性能"
    y-axis "难学/底层" --> "易学/高层"
    quadrant-1 "高性能 + 易学"
    quadrant-2 "高性能 + 底层"
    quadrant-3 "低性能 + 易学"
    quadrant-4 "低性能 + 底层"
    "C": [0.9, 0.15]
    "C++": [0.88, 0.22]
    "Rust": [0.92, 0.28]
    "C#": [0.72, 0.65]
    "Java": [0.65, 0.6]
    "Go": [0.78, 0.58]
    "Python": [0.15, 0.88]
    "JavaScript": [0.1, 0.82]
    "TypeScript": [0.18, 0.78]

C# 在这个图里处于右上靠中的位置:性能不算顶尖但够好,语法抽象层级让开发效率不错。这也是为什么 TubaTools 选用 C# 的原因——写 Windows 桌面工具,C# 是目前综合体验最好的选择。

C# 在语言大家族里的位置

C# 是微软在 2000 年推出的语言,设计师是 Anders Hejlsberg——也是 Turbo Pascal 和 Delphi 的创造者,后来还设计了 TypeScript。这个人做语言的天赋在于:让语法严谨但不啰嗦,让编译器帮你发现尽量多的错误,同时保持足够高的运行效率。

C# 属于 C 语言家族。这个家族的特点是:花括号 {} 表示代码块,分号 ; 结束语句,变量有明确的类型声明。C、C++、Java、C#、JavaScript、TypeScript 都是这个家族的成员。如果你学会了 C#,看 Java 代码会觉得非常眼熟,因为它们的语法有七八成像。

C# 和 .NET 是绑定在一起的。可以把 .NET 理解为一个巨大的工具箱:你写 C# 代码时,随时可以调用 .NET 提供的现成功能——读写文件、网络通信、加密解密、数据库操作、绘制界面。如果没有 .NET,你用 C# 裸写是干不了什么活的。这个关系就像:C# 是你的手,.NET 是宜家仓库里所有的零件,你用手把零件组装成你想要的家具。

TubaTools 这个项目就是用 C# 作为"手",用 .NET 提供的 WinUI 3 框架作为"零件库",搭建出了一个 Windows 桌面工具集。后面你会逐渐看到,项目里每一行 C# 代码都在调用 .NET 的某个功能,从来没有自己从头造过轮子。

如何选择学哪门语言

网上关于"第一门语言应该学什么"的争论从来就没停过。其实这个问题没有标准答案,但有两条原则可以帮你做决定:

第一,看你到底想做什么。想做网站前端,JavaScript/TypeScript 绕不开。想做数据分析和 AI,Python 生态最成熟。想做手机 App,Swift(iOS)或 Kotlin(Android)。想做桌面软件、游戏开发(Unity)、企业级后端,C# 都很合适。

第二,看你的学习目标。如果你的目标只是"学会编程",那选哪门语言其实差别不大。因为编程的核心能力——拆解问题、设计逻辑、调试错误——在一门语言上学到之后,迁移到其他语言的成本很低。Python 对初学者的语法最友好,不用在分号和括号上花精力。C# 或者 Java 对初学者的"类型安全"保护最强,编译器会帮你拦下很多低级错误。C 语言会让你从一开始就理解内存和指针,但学习曲线最陡。

如果你跟着本课程学下去,选 C# 作为第一门语言有几个优势:编译器报错信息清晰,Visual Studio 的自动补全和调试功能很强,.NET 的文档质量在业界是第一梯队,而且你有一个真实项目(TubaTools)可以随时翻源码验证你学到的知识点。

本课小结

编程语言是人写给计算机的指令书。"高级"意味着离人类的思维方式近,离 CPU 远。语言和 CPU 之间靠编译器或者解释器桥接。世界上有几百种编程语言,不是因为前人闲得慌,而是因为不同的任务需要不同的工具,不同的平台绑定不同的生态,不同时代的理念沉淀成不同的语言设计。

C# 是一种编译型(严格说是先编译到 IL 再 JIT 编译到机器码)、强类型、C 家族语法的语言,和 .NET 框架深度绑定,适合 Windows 桌面开发、游戏开发和企业后端。本课程将用 TubaTools 这个真实的 Windows 桌面项目作为学习素材,带你从零学会 C# 和 .NET 开发。

小练习

第 1 题(填空):编程语言的两种翻译方式是 ______ 和 ______。C# 采用的方式是把源代码先编译成 ______,运行时再由 ______ 翻译成机器码。

第 2 题(选择):以下哪个语言属于解释型语言?

A. C++
B. C#
C. Python
D. Go

第 3 题(选择):关于 C# 和 .NET 的关系,以下说法正确的是:

A. C# 可以脱离 .NET 单独使用
B. .NET 只能用 C# 来编程
C. C# 是一门语言,.NET 是一个提供大量现成功能的框架和运行时
D. .NET 是 C# 的旧名字

第 4 题(简答):假设你要开发一个在手机上运行的计算器 App。用 C# 可以做到吗?如果可以的话,需要借助什么框架或工具?如果不可以,为什么?请查阅资料后回答。(提示:搜索 "Xamarin" 或 ".NET MAUI")


练习答案见下页(可在学完后对照检查)

练习答案

第 1 题:编译,解释。中间语言(IL),JIT 编译器。

第 2 题:C。Python 是解释型语言。C++ 和 Go 是编译型,C# 属于编译到中间语言再 JIT 编译的混合方式。

第 3 题:C。C# 和 .NET 是深度绑定但独立的两个东西:C# 是语言规范,.NET 是运行时和类库。.NET 也支持 F# 和 VB.NET 等其他语言。

第 4 题:可以。微软提供了 .NET MAUI(Multi-platform App UI)框架,可以用 C# 写一份代码同时编译到 Android、iOS、Windows 和 macOS。它的前身叫 Xamarin。不过对于纯手机 App,原生方案(Swift/Kotlin)的用户体验和性能通常更好。

 ·