24.总结
24.1 知识点

学习的主要内容

总结讲什么

为什么要讲练结合

如何培养良好的学习习惯

如何快速的提升编程能力

24.2 核心要点速览
输入输出操作
| API | 作用 | 返回值 | 示例 |
|---|---|---|---|
Console.WriteLine |
输出文本并换行 | 无 | Console.WriteLine("Hello"); |
Console.Write |
输出文本但不换行 | 无 | Console.Write("Hello"); |
Console.ReadLine |
读取一行用户输入 | string |
string s = Console.ReadLine(); |
Console.ReadKey |
读取单个按键 | ConsoleKeyInfo |
ConsoleKeyInfo k = Console.ReadKey(); |
注释
三种注释:单行 //、块 /* ... */、文档 ///(用于类/方法说明)。
代码分组
用 #region 折叠代码块,便于阅读长文件。
#region 变量声明
int a = 1;
int b = 2;
#endregion
注意:仅编辑器功能,编译时会被忽略。
基础变量类型
| 分类 | 类型 | 位数 | 取值范围 | 说明 |
|---|---|---|---|---|
| 有符号整型 | sbyte |
8位 | -128 ~ 127 | |
short |
16位 | -3万多 ~ 3万多 | ||
int |
32位 | -21亿多 ~ 21亿多 | 最常用 | |
long |
64位 | -9百万兆 ~ 9百万兆 | ||
| 无符号整型 | byte |
8位 | 0 ~ 255 | |
ushort |
16位 | 0 ~ 6万多 | ||
uint |
32位 | 0 ~ 42亿多 | ||
ulong |
64位 | 0 ~ 18百万兆 | ||
| 浮点数 | float |
32位 | 7-8位有效数字,需加f后缀 |
|
double |
64位 | 15-17位有效数字,默认小数类型 | ||
decimal |
128位 | 27-28位有效数字,适合金钱计算 | ||
| 布尔 | bool |
8位 | true/false |
|
| 字符 | char |
16位 | 单个字符 | 如 'A'、'中' |
| 字符串 | string |
不定 | 引用类型,不可变 |
选择建议:
- 整数用
int,不够用long - 小数用
double,需要高精度用decimal - 判断用
bool - 单字符用
char,文本用string
获取类型内存大小
sizeof 获取类型占用的字节数。
Console.WriteLine(sizeof(int)); // 4
Console.WriteLine(sizeof(double)); // 8
注意:不能用于 string(长度不固定)。
变量命名规则
必须遵守:
- 不能重名
- 不能以数字开头
- 不能用关键字(如
int、string) - 不能有特殊符号(下划线
_除外)
建议规范:
| 命名法 | 格式 | 用途 | 示例 |
|---|---|---|---|
| 驼峰命名法 | 首字母小写,后续单词首字母大写 | 变量 | userName、totalCount |
| 帕斯卡命名法 | 每个单词首字母都大写 | 类名、方法名 | UserInfo、GetData() |
注意:C# 区分大小写,name 和 Name 是两个不同的变量。
常量
值不可变的变量,用 const 声明,必须在声明时初始化。
const float PI = 3.14159f;
const int MAX_SIZE = 100;
// PI = 3.14f; // 错误!常量不能修改
什么时候用:数学常数、配置参数、固定值。
转义字符
以 \ 开头的特殊字符,用于表示无法直接输入的字符。
| 转义符 | 效果 | 示例 | 输出 |
|---|---|---|---|
\' |
单引号 | "\'哈哈哈\'" |
'哈哈哈' |
\" |
双引号 | "\"哈哈哈\"" |
"哈哈哈" |
\n |
换行 | "第一行\n第二行" |
两行文本 |
\\ |
反斜杠 | "C:\\Users" |
C:\Users |
\t |
制表符 | "Name\tAge" |
Name Age |
\b |
退格 | "123\b123" |
12123 |
\a |
警报音 | "\a" |
播放提示音 |
取消转义:字符串前加 @,如 @"C:\Users\file.txt"。
类型转换
隐式转换(自动)
小范围 → 大范围,不丢失数据:
sbyte → short → int → long → float → double
byte → ushort → uint → ulong → float → double
注意:string 和 bool 不参与隐式转换。
显式转换(强制)
| 方法 | 语法 | 说明 | 注意 |
|---|---|---|---|
| 括号强转 | (int)3.14 |
强制转换类型 | 可能丢失精度或溢出 |
| Parse | int.Parse("123") |
字符串转数值 | 格式错误会抛异常 |
| Convert | Convert.ToInt32("123") |
任意类型互转 | 更安全,失败抛异常 |
| ToString | 123.ToString() |
转字符串 | 所有类型都有 |
精度丢失示例:
double d = 1.1234567890123456789;
float f = (float)d; // 1.1234568,丢失精度
int i = (int)1.9f; // 1,直接舍弃小数,不四舍五入
范围溢出示例:
int big = 40000;
short small = (short)big; // -25536,溢出后变成负数
异常捕获
处理程序运行时可能发生的错误,防止程序崩溃。
try
{
int result = int.Parse("abc"); // 可能出错
}
catch (Exception e)
{
Console.WriteLine("出错:" + e.Message); // 出错时执行
}
finally
{
// 无论是否出错都执行,用于清理资源
}
| 块 | 作用 | 必需 |
|---|---|---|
try |
包裹可能出错的代码 | 是 |
catch |
捕获并处理异常 | 是(至少一个) |
finally |
无论如何都执行 | 否 |
运算符
算术运算符
| 运算符 | 作用 | 示例 | 结果 |
|---|---|---|---|
+ |
加法 | 5 + 3 |
8 |
- |
减法 | 5 - 3 |
2 |
* |
乘法 | 5 * 3 |
15 |
/ |
除法 | 5 / 2 |
2(整数除法只保留整数) |
% |
取余 | 5 % 2 |
1 |
复合运算符:+=、-=、*=、/=、%=(仅一种运算,不能混合)。
自增自减:++、--;a++ 先用后加,++a 先加后用。
注意:整数相除只保留整数部分,要得到小数需 5.0 / 2。
关系运算符
> < >= <= == !=,结果为 bool。
bool result = 5 > 3; // true
result = 5 == 3; // false
注意:C# 不能直接用 1 < i < 5,需用逻辑运算符 i > 1 && i < 5。
逻辑运算符
| 运算符 | 作用 | 规则 | 短路特性 |
|---|---|---|---|
&& |
逻辑与 | 两边都true才true | 左边false则右边不执行 |
|| |
逻辑或 | 一边true就true | 左边true则右边不执行 |
! |
逻辑非 | true变false,false变true | 无 |
int a = 1;
bool result = a > 0 || ++a > 1; // 左边true,右边++a不执行
Console.WriteLine(a); // 输出1,a没有被自增
位运算符(了解)
对二进制位进行操作,常用于底层开发、权限控制。
| 运算符 | 作用 | 示例 |
|---|---|---|
& |
位与 | 5 & 3 = 1 |
| |
位或 | 5 | 3 = 7 |
^ |
异或 | 5 ^ 3 = 6 |
~ |
位取反 | ~5 = -6 |
<< |
左移 | 5 << 1 = 10(相当于×2) |
>> |
右移 | 5 >> 1 = 2(相当于÷2) |
三目运算符
// 条件 ? 为真返回 : 为假返回
int max = a > b ? a : b; // a>b则取a,否则取b
运算符优先级(高→低)
() → ! → * / % → + - → > < >= <= → == != → & → ^ → | → && → || → ?:
建议:不确定时多用括号,代码更清晰。
字符串拼接
| 方法 | 语法 | 说明 | 适用场景 |
|---|---|---|---|
+ |
"Hello" + "World" |
简单直接 | 少量拼接 |
+= |
str += "追加" |
复合运算符 | 循环中追加 |
string.Format |
string.Format("{0}岁", 18) |
占位符模板 | 多参数格式化 |
$ 插值 |
$"{name}岁" |
最简洁直观 | 推荐使用 |
Console.WriteLine 也支持占位符:Console.WriteLine("A{0}B", x)(与 string.Format 用法一致)。
注意:+ 拼接是唯一方法,不能用 - * /。
流程控制
条件分支
| 语句 | 语法 | 特点 |
|---|---|---|
if |
if (条件) { ... } |
单分支 |
if-else |
if (条件) { ... } else { ... } |
二选一 |
if-else if-else |
if...else if...else |
多分支 |
switch |
switch(变量) { case 值: ... break; } |
等值判断 |
switch贯穿:多个case执行相同代码时,可省略中间的break。
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
Console.WriteLine("工作日"); // 1-5都执行这里
break;
case 6:
case 7:
Console.WriteLine("周末");
break;
}
循环
| 语句 | 语法 | 执行顺序 | 特点 | 适用场景 |
|---|---|---|---|---|
while |
while (条件) { 循环体 } |
先判断→后执行 | 可能一次都不执行 | 不确定次数 |
do-while |
do { 循环体 } while (条件); |
先执行→后判断 | 至少执行一次 | 至少执行一次 |
for |
for (初始; 条件; 增量) { 循环体 } |
初始化→判断→执行→增量 | 次数明确 | 固定次数 |
循环控制:
break:跳出整个循环continue:跳过本次,进入下一次
24.3 面试题精选
基础题
1. C#中的变量类型及其应用场景
题目
请列举C#中常见的变量类型,并说明在实际开发中如何根据数据特点选择合适的变量类型。
深入解析
C#中的变量类型主要分为三大类:整型、浮点型和特殊类型。
整型包括有符号和无符号两种:
- 有符号:sbyte(1字节)、short(2字节)、int(4字节)、long(8字节)
- 无符号:byte(1字节)、ushort(2字节)、uint(4字节)、ulong(8字节)
浮点型包括:
- float(4字节,单精度)
- double(8字节,双精度)
- decimal(16字节,高精度)
特殊类型包括:bool、char、string等。
选择变量类型时需要考虑三个因素:
- 数据范围:根据数据的取值范围选择合适的类型,如年龄用byte(0-255),一般整数用int,大整数用long
- 精度要求:一般小数用float,需要更高精度用double,涉及金钱计算必须用decimal
- 内存占用:处理大量数据时,选择合适的类型可以显著节省内存
// 示例:游戏开发中的类型选择
byte age = 25; // 年龄范围0-255,用byte节省内存
float position = 1.5f; // 坐标用float,精度足够且节省内存
decimal money = 99.99m; // 金钱计算用decimal,保证精度
答题示例
C#变量类型分整型、浮点型、特殊类型。
整型有 sbyte、short、int、long 及其无符号版本;浮点型有 float、double、decimal。
选择时看数据范围、精度和内存占用。比如游戏坐标用 float,金钱用 decimal,年龄用 byte。
参考文章
- 5.变量
- 6.变量的本质
2. 转义字符的使用方法
题目
请解释什么是转义字符,并列举几个常用的转义字符及其作用。
深入解析
转义字符是以反斜杠\开头的特殊字符,用于在字符串中表示无法直接输入的字符。
常用转义字符:
\n:换行\t:制表符\":双引号\\:反斜杠本身\0:空字符
@符号的作用:
在字符串前加@符号可以取消转义,字符串中的反斜杠会被当作普通字符处理。这在处理文件路径时特别有用。
// 普通字符串中的转义
string str1 = "第一行\n第二行"; // 换行
string str2 = "路径:C:\\Users\\"; // 双反斜杠表示一个反斜杠
// 使用@符号取消转义
string path = @"C:\Users\file.txt"; // 直接写反斜杠
string json = @"{""name"":""test""}"; // 双引号表示一个双引号
答题示例
转义字符是用反斜杠开头的特殊字符,比如
\n换行、\t制表符、\"双引号。字符串前加
@可以取消转义,处理文件路径时很方便,比如@"C:\Users\file.txt"。
参考文章
- 9.转义字符
3. 类型转换的两种方式
题目
请简述C#中的隐式转换和显式转换的区别,并举例说明。
深入解析
C#中的类型转换分为隐式转换和显式转换两种。
隐式转换:
- 由编译器自动完成,不需要手动干预
- 发生在小范围类型向大范围类型转换时
- 不会丢失数据精度
显式转换:
- 需要手动指定转换类型
- 发生在大范围类型向小范围类型转换时
- 可能丢失数据精度
常见的显式转换方法:
- 括号强转:直接进行类型转换,可能导致精度丢失
- Parse方法:将字符串转换为数值类型,格式错误时抛出异常
- Convert类方法:提供更安全的转换,会处理边界情况
// 隐式转换
int i = 10;
long l = i; // int → long,自动转换
// 显式转换
double d = 3.14;
int j = (int)d; // double → int,丢失小数部分
// Parse方法
int num = int.Parse("123"); // 字符串转整数
// Convert方法
int num2 = Convert.ToInt32(3.9); // 四舍五入
答题示例
隐式转换是编译器自动完成的,小转大,比如 int 到 long。
显式转换需要手动写,大转小,可能丢精度,比如 double 到 int。
常用方法有括号强转、Parse、Convert。
参考文章
- 10.类型转换-隐式转换
- 11.类型转换-显式转换
进阶题
1. 逻辑运算符的短路特性
题目
请解释C#中逻辑运算符的短路特性,并举例说明这一特性在实际开发中的应用。
深入解析
C#中的逻辑运算符&&和||具有短路特性,这是指在某些情况下,运算符右侧的表达式不会被执行。
短路特性原理:
&&运算符:如果左侧条件为false,右侧条件不会执行||运算符:如果左侧条件为true,右侧条件不会执行
实际应用场景:
- 空引用检查:在访问对象成员前先检查是否为null
- 性能优化:避免不必要的计算
- 防止异常:避免执行可能抛出异常的代码
// 空引用检查
if (obj != null && obj.DoSomething())
{
// 当obj为null时,DoSomething()不会执行
}
// 性能优化
if (IsCacheValid() || ExpensiveCalculation())
{
// 如果缓存有效,不会执行昂贵的计算
}
// 注意:不要在短路运算符右侧放置有副作用的表达式
int a = 0;
if (false && ++a > 0) // a不会自增
{
}
Console.WriteLine(a); // 输出:0
答题示例
&&左边 false 就不执行右边,||左边 true 就不执行右边。常用于空引用检查,比如
obj != null && obj.Method(),避免空异常。注意右边不要放有副作用的表达式。
参考文章
- 16.运算符-逻辑运算符
2. try-catch异常处理的最佳实践
题目
请说明try-catch异常处理的使用场景和注意事项,并给出最佳实践建议。
深入解析
try-catch异常处理用于捕获和处理程序运行时可能发生的错误,防止程序崩溃。
基本结构:
try块:包裹可能出错的代码catch块:捕获并处理异常finally块:无论是否发生异常都会执行,用于释放资源
适用场景:
- 用户输入处理
- 文件操作
- 网络请求
- 类型转换
最佳实践:
- 不要用异常处理代替正常的条件判断(会影响性能)
- 捕获异常后要进行适当处理(如记录日志或提示用户)
- 在finally块中释放资源(如关闭文件流)
- 捕获具体的异常类型,而不是笼统的Exception
// 正确做法:具体异常类型 + 资源释放
try
{
string content = File.ReadAllText("data.txt");
}
catch (FileNotFoundException ex)
{
Console.WriteLine($"文件不存在:{ex.FileName}");
}
catch (IOException ex)
{
Console.WriteLine($"读取失败:{ex.Message}");
}
finally
{
// 释放资源
}
// 错误做法:用异常处理代替条件判断
try
{
int num = int.Parse(input);
}
catch
{
// 应该用int.TryParse代替
}
答题示例
try-catch 用于捕获运行时错误。
适用场景有文件操作、网络请求等。
注意不要用异常代替条件判断,要捕获具体异常类型,finally 里释放资源。可预期的错误用条件判断提前检查。
参考文章
- 12.异常捕获
3. switch与if-else的选择
题目
请说明switch语句和if-else语句的区别,以及在什么情况下应该选择switch而不是if-else。
深入解析
switch语句和if-else语句都是条件分支语句,但适用场景不同。
switch语句特点:
- 适合等值判断,特别是多个固定值的情况
- 代码结构更清晰
- 可以使用case贯穿特性,让多个case执行相同代码
- 编译器可能优化为跳转表,性能更好
if-else语句特点:
- 适合范围判断和复杂条件
- 更灵活,可以处理任意布尔表达式
- 条件判断顺序影响执行效率
选择建议:
- 判断变量是否等于多个固定值:优先使用switch
- 范围判断或复杂条件:使用if-else
// switch适合的场景:等值判断
switch (dayOfWeek)
{
case 1:
Console.WriteLine("星期一");
break;
case 2:
Console.WriteLine("星期二");
break;
// ...
}
// if-else适合的场景:范围判断
if (score >= 90)
{
Console.WriteLine("优秀");
}
else if (score >= 60)
{
Console.WriteLine("及格");
}
else
{
Console.WriteLine("不及格");
}
答题示例
switch 适合等值判断,多个固定值时代码更清晰,性能可能更好。
if-else 适合范围判断和复杂条件。
比如判断星期几用 switch,判断分数等级用 if-else。
参考文章
- 19.条件分支语句-if
- 20.条件分支语句-switch
深度题
1. 变量类型选择对性能的影响
题目
请分析C#中不同变量类型的内存占用情况,并说明类型选择对程序性能的影响。
深入解析
C#中不同变量类型的内存占用不同,类型选择直接影响程序性能。
各类型内存占用:
| 类型 | 占用字节 |
|---|---|
| byte, sbyte | 1字节 |
| short, ushort, char | 2字节 |
| int, uint, float | 4字节 |
| long, ulong, double | 8字节 |
| decimal | 16字节 |
性能影响(紧扣系列:第5、6篇讲的是各类型内存占用与取值范围):
- 内存占用:用
sizeof可知各类型字节数;选小类型(如 byte、float)可减少内存,利于缓存 - 取值范围:选型时要避免溢出(如 short 装不下 40000 会变成负数)
- 实际选择:年龄用 byte、坐标用 float、金钱用 decimal,既保证正确又控制占用
游戏开发中的优化策略:
- 存储大量NPC年龄使用byte
- 坐标使用float而非double
- 状态标记使用位运算而非多个bool
// 优化示例
// 不好的做法
bool isPoisoned;
bool isAccelerated;
bool isInvincible;
// ... 32个bool变量,占用32字节
// 好的做法
int stateFlags; // 用位存储32个状态,只占4字节
const int POISONED = 1 << 0;
const int ACCELERATED = 1 << 1;
const int INVINCIBLE = 1 << 2;
// 添加状态
stateFlags |= POISONED;
// 检查状态
if ((stateFlags & POISONED) != 0) { }
答题示例
不同类型内存占用不同,byte 1 字节,int 4 字节,double 8 字节,可用 sizeof 查看。
选型时根据范围和精度来选,避免溢出和精度丢失。
游戏开发里坐标用 float、年龄用 byte、状态用位运算打包,能显著节省内存、提升性能。
参考文章
- 5.变量
- 6.变量的本质
2. 位运算在游戏开发中的应用
题目
请说明位运算符的作用,并举例说明位运算在游戏开发中的实际应用场景。
深入解析
位运算符用于对二进制位进行直接操作,在游戏开发中有重要应用。
位运算符:
&(位与):两位都为1时结果为1|(位或):有一位为1时结果为1^(异或):两位不同时结果为1~(位取反):0变1,1变0<<(左移):左移n位,相当于乘以2^n>>(右移):右移n位,相当于除以2^n
游戏开发应用场景:
- 状态管理:用一个整数的每一位表示一个状态
- 权限控制:用位表示不同权限
- 配置选项:用位存储多个开关选项
// 状态管理示例
[Flags]
enum PlayerState
{
None = 0,
Poisoned = 1, // 0001
Accelerated = 2, // 0010
Invincible = 4, // 0100
Invisible = 8 // 1000
}
PlayerState state = PlayerState.Poisoned | PlayerState.Accelerated;
// 检查状态
if (state.HasFlag(PlayerState.Poisoned))
{
// 处理中毒状态
}
// 移除状态
state &= ~PlayerState.Poisoned;
// 切换状态
state ^= PlayerState.Invincible;
优势:
- 节省内存:一个int存储32个状态
- 操作快速:位运算是CPU原生支持的
- 便于网络传输:状态数据紧凑
答题示例
位运算符有
&与、|或、^异或、~取反、<<左移、>>右移。游戏开发中常用于状态管理,一个 int 存 32 个状态,比 32 个 bool 省内存。
比如
state |= 1添加状态,state &= ~1移除状态,state & 1检查状态。
参考文章
- 17.运算符-位运算符
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com