委托、事件与文件 IO 复习#
对应笔记:委托与 Lambda、事件、Array 数组方法、文件 IO 概览、File 类与 FileInfo 类、StreamReader 与 StreamWriter、FileStream 字节流、BinaryReader 与 BinaryWriter 建议用时:60 分钟。
一、选择题#
1. 什么是委托(Delegate)?
- A. 一种数据类型,用来存储方法
- B. 一种循环结构
- C. 一个类
- D. 一种异常类型
答案
A。委托是"函数的数据类型",可以把方法赋值给委托变量,像调用方法一样调用。C# 中函数也是数据。
2. Func<int, bool> 委托的含义是?
- A. 无参返回 bool
- B. 接收 int 参数,返回 bool
- C. 接收两个参数
- D. 无返回值
答案
B。Func 最后一个泛型参数是返回值类型,前面的都是参数类型。Func<int, bool> = 接收 int、返回 bool。无返回值的用 Action。
3. 委托变量为 null 时直接调用会?
- A. 返回 null
- B. 抛 NullReferenceException
- C. 自动忽略
- D. 返回 false
答案
B。安全做法:del?.Invoke(args)(空条件运算符)或先判断 if (del != null)。
4. 事件(event)与普通委托的区别,错误的是?
- A. 事件外部只能订阅(+=)或取消(-=)
- B. 事件只能在声明类内部触发
- C. 事件外部可以随意触发
- D. 事件用于发布-订阅模式
答案
C。事件只能在声明它的类内部触发,外部不能直接调用;外部只能 += 订阅 / -= 取消。
5. StreamReader 与 StreamWriter 主要用于?
- A. 二进制数据读写
- B. 文本数据逐行/逐字符读写
- C. 数据库连接
- D. 网络通信
答案
B。StreamReader/Writer 是文本流;BinaryReader/Writer 是二进制流;FileStream 是底层字节流。
6. using 语句的作用是?
- A. 引入命名空间
- B. 确保资源(IDisposable)在代码块结束时自动释放
- C. 定义别名
- D. 声明变量
答案
B。using (var r = new Resource()) { } 会在块结束时自动调用 Dispose(),即使发生异常。FileStream、StreamReader 等都实现了 IDisposable,应优先用 using。
7. File.ReadAllLines(path) 的返回值是?
- A. string
- B. string[](每行一个元素)
- C. List<string>
- D. byte[]
> [!success]- 答案 > B。ReadAllText 返回 string(整个文件);ReadAllLines 返回 string[](每行一个元素)。
二、填空题#
1. Lambda 表达式的基本格式:==_== ==== ==_== ====,如 v => v % 2 == 0。
答案
(参数列表) => { 方法体 } 或简化 参数 => 表达式(单表达式可省略大括号和 return)。
2. 内置委托类型:无返回值用 ==_== ==== ==_== ====,有返回值用 ==_== ==== ==_== ====。
答案
Action<参数...>;Func<参数..., 返回值>。
3. 多播委托用 ==_== ==== ==_== ==== 添加方法、==_== ==== ==_== ==== 移除方法。
答案
+=;-=。调用时按添加顺序依次执行所有方法。
4. 文件路径基础:以盘符开头的是 ==_== ==== ==_== ==== 路径,./ 表示 ==_== ==== ==_== ====,../ 表示 ==_== ==== ==_== ====。
答案
绝对路径;当前目录;上一级目录。
5. BinaryWriter.Write(12345) 写入的是 ==_== ==== ==_== ==== 类型数据,读取时用 ==_== ==== ==_== ==== 方法。
答案
int(整数);ReadInt32()。写入和读取的顺序、类型必须一致。
6. 文本文件读写推荐用 ==_== ==== ==_== ==== 类,二进制用 ==_== ==== ==_== ==== 类,底层字节流用 ==_== ==== ==_== ==== 类。
答案
StreamReader/StreamWriter;BinaryReader/BinaryWriter;FileStream。
三、代码分析题#
1. 写出输出结果。
public delegate void MyDel(string s);
MyDel d = (s) => Console.WriteLine("A:" + s);
d += (s) => Console.WriteLine("B:" + s);
d("hi");
d -= /* 第一个方法 */;
2. 写出输出结果。
int[] nums = { 1, 2, 3, 4, 5, 6 };
var r1 = Array.Find(nums, n => n % 2 == 0);
var r2 = Array.FindAll(nums, n => n % 2 == 0);
var r3 = Array.Exists(nums, n => n > 10);
答案
r1 = 2(Find 返回第一个满足条件的元素);r2 = {2, 4, 6}(FindAll 返回所有满足条件的数组);r3 = false(Exists 判断是否存在)。
3. 下列代码有什么问题?
class Boiler
{
public event Action<double> THigh;
public void Check(double t)
{
if (t > 100) THigh(t); // 这里可能有什么问题?
}
}
答案
如果没有人订阅事件,THigh 为 null,直接调用会抛 NullReferenceException。应改为 THigh?.Invoke(t);。
4. 写出读取文本文件每一行的正确代码(using 写法)。
答案
四、编程题#
1. 定义委托,接收两个 int 返回 int,用 Lambda 实现加法并调用。
2. 自定义事件:发布者(温度计)温度超过 100 触发报警事件,订阅者(报警器)输出"温度过高"。
答案
```csharp
> class Thermometer > { > public event Action<int> Overheat; > public void SetTemp(int t) > { > if (t > 100) Overheat?.Invoke(t); > } > } > class Alarm > { > public void Ring(int t) { Console.WriteLine($"温度过高:{t}"); } > } > // 使用 > Thermometer tm = new Thermometer(); > Alarm alarm = new Alarm(); > tm.Overheat += alarm.Ring; > tm.SetTemp(120); // 触发 → "温度过高:120" > ```
3. 用 File 类实现:追加一行文本到文件,然后读取全部行输出。
答案
4. 用 Directory 类实现:判断目录是否存在,不存在则创建,并列出其中的文件。
答案
5. 用 BinaryWriter 写入 int 和 string,再用 BinaryReader 读回。
答案
// 写入
using (FileStream fs = new FileStream("data.bin", FileMode.Create, FileAccess.Write))
using (BinaryWriter bw = new BinaryWriter(fs))
{
bw.Write(12345);
bw.Write("hello");
}
// 读取(顺序必须一致)
using (FileStream fs = new FileStream("data.bin", FileMode.Open, FileAccess.Read))
using (BinaryReader br = new BinaryReader(fs))
{
Console.WriteLine(br.ReadInt32()); // 12345
Console.WriteLine(br.ReadString()); // hello
}
6. 用泛型方法实现:打印任意类型数组的所有元素。
答案
知识卡片#
委托是什么?
函数的数据类型。声明委托类型可保存方法,像调用方法一样调用。
delegate 返回类型 委托名(参数列表)。
Func 与 Action 的区别?
Func 有返回值(最后泛型参数是返回类型);Action 无返回值。
多播委托?
一个委托存多个方法,
+=添加、-=移除,调用时按顺序依次执行。
委托调用的空值保护?
del?.Invoke(args)或先判空。null 直接调用会抛 NullReferenceException。
事件的三要素?
发布者(声明并触发事件)、订阅者(提供处理方法)、事件(+= / -= 连接双方)。
事件与委托的区别?
事件只能在声明类内部触发,外部只能订阅/取消;委托可以直接调用。
File 与 FileInfo 的区别?
File 是静态类,一次性操作(File.ReadAllText);FileInfo 是实例类,多次操作同一文件或查详细信息。
FileStream 与 StreamReader 的区别?
FileStream 底层字节流;StreamReader 基于 FileStream 的文本流,逐行读写更方便。
using 语句的作用?
自动释放 IDisposable 资源(Close + Dispose),即使异常也保证释放;文件流、读写器都应使用。
二进制读写注意什么?
写入与读取的顺序、类型必须一致(Write(int) 用 ReadInt32 读回);写入后 Flush 确保落盘。
相关笔记#
- 委托与 Lambda — 委托与 Lambda
- 事件 — 事件
- Array 数组方法 — Array.Find(委托应用)
- 泛型 — 泛型方法
- 文件 IO 概览 — IO 总览
- File 类与 FileInfo 类 — 文件操作
- StreamReader 与 StreamWriter — 文本流
- FileStream 字节流 — 字节流
- BinaryReader 与 BinaryWriter — 二进制
- C# 复习总览 — 复习总览