前置说明:
- C# 是强类型、面向对象编程语言,运行在 .NET 平台(.NET 6/.NET 7/.NET 8 推荐)
- 开发工具:Visual Studio 2022 或者 VS Code + .NET SDK
- 学习思路:先看懂代码,理解底层执行机理,亲手敲代码,观察运行结果,不要只复制粘贴。
- 术语尽量通俗,每段都附带完整示例 + 逐行拆解 + 机理说明 + 实际用途
1. 第一个 C# 程序:HelloWorld
完整代码
cs
using System;
namespace FirstDemo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
逐行拆解 + 机理
cs
using System;
using:引入命名空间 。System是.NET 内置核心命名空间,里面放了控制台Console类。- 机理:C# 默认不会加载所有内置工具,需要
using告诉编译器:我要使用System里面的东西。 - 如果删掉这一行,写
Console.WriteLine会报错,编译器找不到Console。
cs
namespace FirstDemo
namespace命名空间:相当于文件夹,用来把代码归类,防止不同代码里类名冲突。FirstDemo是自定义命名空间名字,可以改成任意合法名称。- 机理:项目越来越大,多个类重名时,命名空间区分它们。例如
A.Project.User和B.Project.User是两个不同类。
cs
class Program
class:定义类。C# 是面向对象语言,几乎所有代码都必须写在类里面。Program类名,首字母大写是 C# 约定规范。
cs
static void Main(string[] args)
✅ 程序入口方法,C# 程序从这里开始执行,固定写法。
static:静态。表示这个方法属于类本身,不需要创建对象就可以直接调用。void:返回值类型。void = 无返回值,执行完不返回任何数据。Main:固定名字,编译器识别这是程序入口。首字母必须大写。string[] args:字符串数组,接收命令行启动程序时传入的参数,可以暂时理解为固定模板。
cs
Console.WriteLine("Hello World!");
Console:System 命名空间下的控制台类,负责控制台读写。WriteLine():方法,作用:输出文字,输出完成自动换行。"Hello World!":字符串字面量,双引号包裹。;:C# 语句结束标记,每一条执行语句末尾必须加分号。
机理:编译器读到分号,代表这一条指令结束。忘记写分号直接编译报错。
运行流程(非常重要,新手要记住)
- 编译器扫描代码,找到
Main方法 - 从
Main内部第一行开始自上而下执行 - 执行
Console.WriteLine,把字符串交给操作系统控制台打印 - Main 执行完毕,程序退出
实际用途:所有 C# 控制台程序都以 Main 为入口,桌面程序、后端服务底层也有类似入口。
2. 基础语法规则
2.1 大小写敏感
C# 区分大小写 Console ✔️ console ❌ 编译器认为这是两个不同名字。
2.2 大括号 { }
大括号用来划定代码块范围 类、方法、if、循环都需要大括号,一对{}代表一个完整代码块。
cs
{
// 代码块内部
}
机理:大括号定义作用域,代码块内部定义的变量,出了大括号就不能访问。
2.3 注释
注释不会被编译器编译执行,仅给人阅读。
cs
// 单行注释,从//到本行末尾
/*
多行注释
可以跨越多行
*/
3. 变量与数据类型(C# 核心重点)
变量:内存中的一块存储空间,用来存放数据。 C# 是强类型语言 :声明变量时,必须指定数据类型,一旦声明,类型不能随便更改。
3.1 常用基础值类型
| 类型 | 说明 | 示例 |
|---|---|---|
int |
整数,范围大约 -21 亿~21 亿 | int a = 10; |
double |
双精度浮点数(小数) | double b = 3.14; |
bool |
布尔,只有 true /false | bool flag = true; |
char |
单个字符,单引号包裹 | char c = 'A'; |
long |
长整数,更大范围整数 | long num = 10000000000; |
float |
单精度小数,后面加 f | float f = 2.5f; |
值类型:变量保存的就是数据本身,存储在栈内存。
3.2 string 字符串(引用类型)
cs
string name = "张三";
string:字符串,存放一串字符,双引号
string 是引用类型:变量保存的不是字符串本身,而是堆内存地址。
3.3 变量声明语法
两种写法:
- 完整写法:
类型 变量名 = 值;
cs
int age = 18;
- 先声明,后赋值
cs
int score;
score = 90;
⚠️ C# 局部变量必须赋值之后才能读取,未赋值直接使用编译报错。
示例代码
cs
using System;
namespace VarDemo
{
class Program
{
static void Main(string[] args)
{
int age = 20;
double height = 1.75;
bool isStudent = true;
char gender = '男';
string name = "小明";
Console.WriteLine("姓名:" + name);
Console.WriteLine("年龄:" + age);
Console.WriteLine("身高:" + height);
Console.WriteLine("是否学生:" + isStudent);
}
}
}
机理讲解
- 进入 Main 方法,依次在栈内存开辟空间
- age:int,存入 20
- height:double 存入 1.75
- isStudent:bool 存入 true
- gender:char 存入 ' 男'
- name:string,栈上保存地址,"小明" 存放在堆内存
Console.WriteLine("姓名:"+name):+在这里是字符串拼接,把文本和变量内容拼成一个字符串输出。
var 隐式类型(新手容易混淆)
cs
var num = 100;
var:让编译器自动推断变量类型 。编译器看右边100,自动识别num是int。
⚠️ 注意:var 只是简写,C# 仍然是强类型,一旦推断完成,变量类型固定,不能再存字符串。
cs
var num = 100;
num = "abc"; // 编译报错!num已经是int类型
变量命名规范
- 只能由字母、数字、下划线组成
- 不能以数字开头
- 不能使用 C# 关键字:
int、class、static、if等不能做变量名 - 推荐:小驼峰命名:
userName(变量);大驼峰UserName(类、方法)
4. 常量 const
常量:一旦赋值,程序运行期间值不能修改。
cs
const double PI = 3.1415926;
机理:编译时就把常量值嵌入代码,运行时不允许修改。
cs
using System;
namespace ConstDemo
{
class Program
{
static void Main(string[] args)
{
const double PI = 3.1415926;
double r = 5;
double area = PI * r * r;
Console.WriteLine("圆面积=" + area);
// PI = 3.14; // 取消注释,直接编译报错,常量不可修改
}
}
}
实际用途:固定不变参数,圆周率、税率、固定配置,防止代码里误修改。
5. 运算符
5.1 算术运算符
+ - * / %
cs
int a = 10;
int b = 3;
Console.WriteLine(a + b); //13
Console.WriteLine(a - b); //7
Console.WriteLine(a * b); //30
Console.WriteLine(a / b); //3 【重点】整数除以整数,结果仍然是整数,小数部分直接舍弃!
Console.WriteLine(a % b); //1 取余数,10除以3余1
机理:
int / int整数除法,只保留商。想要小数结果,至少一个操作数是 double
cs
Console.WriteLine(10 / 3.0); //3.3333333333333335
自增自减 ++ --
cs
int x = 5;
x++; //等价 x = x +1; x变成6
int y = 5;
y--; //等价 y = y -1; y变成4
++前置后置区别:
cs
int a = 2;
int res1 = a++; //后置++:先把a当前值赋值给res1,a再+1。res1=2,a=3
int b = 2;
int res2 = ++b; //前置++:b先+1,再赋值。res2=3,b=3
5.2 赋值运算符
= += -= *= /=
cs
int num = 10;
num += 5; // num = num +5 → num=15
num -= 2; // num = num -2 → num=13
5.3 比较运算符
结果一定是bool(true/false) > < >= <= == !=
⚠️ 判断相等是
==,单个=是赋值!新手高频踩坑点
cs
int a = 10;
Console.WriteLine(a == 10); // true
Console.WriteLine(a != 5); // true 不等于
5.4 逻辑运算符
&& 逻辑与(并且):两边都 true,结果才 true || 逻辑或(或者):任意一边 true,结果 true ! 逻辑非:取反
短路特性(机理重点)
&&:左边 false,右边代码不会执行||:左边 true,右边代码不会执行
int age = 18;
bool res = age >=18 && age <=60; //年龄大于等于18并且小于等于60
6. 控制台输入输出
Console.WriteLine():输出 + 换行 Console.Write():输出不换行 Console.ReadLine():读取控制台一行输入,返回 string 字符串
示例:读取用户输入数字
cs
using System;
namespace InputDemo
{
class Program
{
static void Main(string[] args)
{
Console.Write("请输入你的年龄:");
string inputStr = Console.ReadLine(); //读取用户输入,得到字符串
int age = Convert.ToInt32(inputStr); //把字符串转为int整数
Console.WriteLine("你的年龄是:" + age);
}
}
}
机理拆解
Console.ReadLine():程序暂停,等待用户在控制台打字,回车之后,把输入文本以字符串返回。Convert.ToInt32():类型转换。用户输入的是文本字符串,不能直接当成数字计算,必须转换。
坑点:用户输入
abc,转 int 会直接程序崩溃,后面学习异常处理解决。
7. 分支语句:条件判断
7.1 if else
语法:
cs
if(条件表达式)
{
//条件为true执行
}
else
{
//条件为false执行
}
示例
cs
using System;
namespace IfDemo
{
class Program
{
static void Main(string[] args)
{
Console.Write("输入分数:");
string input = Console.ReadLine();
int score = Convert.ToInt32(input);
if (score >= 60)
{
Console.WriteLine("及格");
}
else
{
Console.WriteLine("不及格");
}
}
}
}
机理:括号里面表达式结果必须是bool。true 执行 if 块,false 执行 else 块。
多分支 if else if
cs
if (score >=90)
{
Console.WriteLine("优秀");
}
else if(score >=80)
{
Console.WriteLine("良好");
}
else if(score >=60)
{
Console.WriteLine("及格");
}
else
{
Console.WriteLine("不及格");
}
执行顺序:从上往下依次判断,命中一个分支之后,剩下分支不再判断。
7.2 switch 语句
适合固定值匹配场景
cs
using System;
namespace SwitchDemo
{
class Program
{
static void Main(string[] args)
{
Console.Write("输入数字1-3:");
string input = Console.ReadLine();
int num = Convert.ToInt32(input);
switch(num)
{
case 1:
Console.WriteLine("选项一");
break;
case 2:
Console.WriteLine("选项二");
break;
case 3:
Console.WriteLine("选项三");
break;
default:
Console.WriteLine("输入不在1~3");
break;
}
}
}
}
机理:拿
num的值依次匹配 case。break必须写,作用跳出 switch。不写 break 会穿透到下一个 case(C# 默认禁止穿透)。 default:所有 case 都不匹配时执行,类似 else。
使用场景:固定枚举值;范围判断优先用 if else。
8. 循环语句:重复执行代码块
8.1 while 循环
语法:
cs
while(条件)
{
//循环体,条件true就重复执行
}
特点:先判断条件,条件成立才执行循环体。有可能一次都不执行
示例:打印 1 到 5
cs
using System;
namespace WhileDemo
{
class Program
{
static void Main(string[] args)
{
int i = 1;
while(i <=5)
{
Console.WriteLine(i);
i++;
}
}
}
}
执行流程:
- i=1 判断
1<=5true → 打印,i++ → i=2 - i=2 判断 true →打印,i++
- i=5 true →打印,i++ →i=6
- i=6 判断
6<=5false →循环结束
⚠️ 死循环:条件永远 true。忘记写i++,i 一直等于 1,程序无限循环。
8.2 do while
cs
do
{
//循环体
}while(条件);
特点:先执行一次循环体,再判断条件。至少执行一次
cs
int i = 10;
do
{
Console.WriteLine(i);
i++;
}while(i <=5);
输出:10。虽然条件不成立,但 do 里面代码先跑一遍。
8.3 for 循环(最常用)
语法:
cs
for(初始化;条件;迭代)
{
循环体
}
示例:打印 1~5
cs
for(int i=1; i<=5; i++)
{
Console.WriteLine(i);
}
执行机理(顺序固定)
- 初始化:
int i=1【只执行一次】 - 判断条件
i<=5 - true →执行循环体
- 执行迭代
i++ - 返回第 2 步判断条件;false →退出循环
适用场景:循环次数已知,优先 for 循环。循环次数不确定,优先 while。
8.4 foreach 循环
专门遍历数组、集合,后面数组部分演示。
break 和 continue
break:立刻跳出整个循环,循环终止continue:结束本次循环,直接跳到条件判断,开启下一轮
cs
for(int i=1;i<=5;i++)
{
if(i ==3)
{
continue;
}
Console.WriteLine(i);
}
输出:1,2,4,5 机理:i=3 时触发 continue,不再执行后面打印语句,直接i++进入下一轮判断。
9. 数组 Array
数组:存储一组相同类型数据,连续内存空间。
数组长度一旦创建,不可修改。
一维数组声明
写法 1:
cs
int[] nums = new int[5]; //创建长度5的int数组,默认值0
nums[0] = 10;
nums[1] = 20;
nums[2] = 30;
nums[3] = 40;
nums[4] = 50;
写法 2:初始化直接赋值
cs
int[] nums = {10,20,30,40,50};
数组下标从 0 开始!长度 5 数组下标 0~4。访问
nums[5]下标越界,程序崩溃。
for 遍历数组
cs
using System;
namespace ArrayDemo
{
class Program
{
static void Main(string[] args)
{
int[] nums = {10,20,30,40,50};
for(int i=0;i<nums.Length;i++)
{
Console.WriteLine(nums[i]);
}
}
}
}
nums.Length 获取数组元素个数。
foreach 遍历(只读遍历)
cs
foreach(int n in nums)
{
Console.WriteLine(n);
}
机理:依次取出数组每一个元素放到变量 n,不能修改下标,适合单纯读取遍历。
10. 方法(函数)
方法:把一段重复使用的代码封装成独立块,实现代码复用。 语法模板
cs
修饰符 返回值类型 方法名(参数列表)
{
//方法体
return 返回值; //如果返回值是void,不需要return
}
示例:写一个加法方法
cs
using System;
namespace MethodDemo
{
class Program
{
static int Add(int a, int b)
{
int res = a + b;
return res; //把结果返回给调用处
}
static void Main(string[] args)
{
int result = Add(3,5); //调用方法,传入实参3和5
Console.WriteLine(result);
}
}
}
逐段机理拆解
static int Add(int a, int b)static:静态方法,Main 是静态,静态方法只能直接调用静态方法int:返回值类型,方法执行完返回 intAdd:方法名int a,int b:形参,相当于方法内部局部变量,接收调用时传入数据
Add(3,5):调用,3和5是实参。实参依次赋值给形参 a=3,b=5- 进入 Add 方法内部计算,
return res把结果传回 Main 调用位置 - 返回值赋值给变量
result
void 无返回值方法:
cs
static void PrintHello(string name)
{
Console.WriteLine("你好:"+name);
}
static void Main(string[] args)
{
PrintHello("小李");
}
作用:代码复用,减少重复代码;拆分复杂程序,让结构清晰。
参数:值传递(重点)
C# 默认方法传参是值传递:传递的是副本。方法内部修改形参,不会影响外面原始变量。
cs
static void Change(int x)
{
x = 100;
Console.WriteLine("方法内x="+x);
}
static void Main(string[] args)
{
int num = 10;
Change(num);
Console.WriteLine("方法外num="+num);
}
输出:
cs
方法内x=100
方法外num=10
机理:调用Change(num),拷贝一份 num 的值给 x。x 和 num 是两块独立内存。修改 x,不会影响外面 num。
11. 简单面向对象入门:类与对象
C# 是面向对象语言。
- 类(Class):模板、图纸,描述一类事物拥有哪些特征(字段 / 属性)和行为(方法)
- 对象(Object):根据类创建出来的实例。
示例:Person 类
cs
using System;
namespace OopDemo
{
class Person
{
//字段:特征
public string name;
public int age;
//方法:行为
public void SayHello()
{
Console.WriteLine($"大家好,我叫{name},今年{age}");
}
}
class Program
{
static void Main(string[] args)
{
//new 创建对象
Person p1 = new Person();
p1.name = "张三";
p1.age = 20;
p1.SayHello();
Person p2 = new Person();
p2.name = "李四";
p2.age = 22;
p2.SayHello();
}
}
}
机理
Person是类(模板),定义人有名字、年龄,可以打招呼。new Person():在堆内存创建 Person 对象实例,返回对象地址,赋值给栈上变量 p1。- p1、p2 是两个独立对象,各自拥有自己的 name 和 age。修改 p1 不会影响 p2。
实际价值:现实业务建模,用户、订单、商品都可以封装成类,是 C# 开发核心。