C#核心技术四剑客:泛型、字典、文件IO与委托从入门到精通
·
一、泛型(Generics)独立详解
1. 泛型基础概念
// 为什么要用泛型?
// 1. 类型安全 - 编译时检查
// 2. 代码重用 - 一套代码处理多种类型
// 3. 性能优化 - 避免装箱拆箱
// 泛型类定义
public class Repository<T>
{
private T _item;
public T GetItem() => _item;
public void SetItem(T item) => _item = item;
}
// 使用
Repository<int> intRepo = new Repository<int>();
Repository<string> stringRepo = new Repository<string>();
2. 泛型方法
// 独立泛型方法
public T Max<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) > 0 ? a : b;
}
// 方法类型推断(编译器自动推断T)
int maxNum = Max(5, 10); // T推断为int
string maxStr = Max("A", "B"); // T推断为string
3. 泛型约束类型
// 主要约束类型
where T : class // 必须是引用类型
where T : struct // 必须是值类型(不包括可空类型)
where T : new() // 必须有无参构造函数
where T : BaseClass // 必须继承自指定基类
where T : IInterface // 必须实现指定接口
where T : unmanaged // 必须是非托管类型(C# 7.3+)
where T : notnull // 必须是非空类型(C# 8.0+)
// 约束组合示例
public class Factory<T> where T : class, ICloneable, new()
{
public T Create() => new T();
}
4. 泛型接口与继承
// 泛型接口
public interface IRepository<T>
{
void Add(T item);
T Get(int id);
}
// 实现泛型接口
public class UserRepository : IRepository<User>
{
public void Add(User user) { /* 实现 */ }
public User Get(int id) { /* 实现 */ }
}
// 泛型继承
public class BaseClass<T> { }
public class DerivedClass<T> : BaseClass<T> { }
5. 协变与逆变
// 协变 (out) - 允许返回更具体的类型
interface IProducer<out T>
{
T Produce();
}
// 逆变 (in) - 允许接受更泛化的类型
interface IConsumer<in T>
{
void Consume(T item);
}
// 使用示例
IProducer<Dog> dogProducer = new DogProducer();
IProducer<Animal> animalProducer = dogProducer; // 协变,安全
IConsumer<Animal> animalConsumer = new AnimalConsumer();
IConsumer<Dog> dogConsumer = animalConsumer; // 逆变,安全
6. default关键字
// default值
T GetDefaultValue<T>()
{
return default(T); // 引用类型返回null,值类型返回0
}
// C# 7.1+ 简写
T GetDefaultValue<T>() => default;
7. 泛型与反射
// 运行时泛型类型操作
Type genericListType = typeof(List<>);
Type stringListType = genericListType.MakeGenericType(typeof(string));
// 创建泛型实例
Type repoType = typeof(Repository<>);
Type userRepoType = repoType.MakeGenericType(typeof(User));
object userRepo = Activator.CreateInstance(userRepoType);
8. 泛型性能注意
// 避免值类型装箱
public class ValueContainer<T> where T : struct
{
// 直接存储值类型,无装箱开销
private T _value;
}
// 使用约束限制避免性能损失
public void Process<T>(T item) where T : struct
{
// 对于值类型,避免使用object转换
}
二、字典(Dictionary)重点回顾
1. 核心特性
// 键值对集合
Dictionary<string, int> scores = new Dictionary<string, int>();
// 重要特性:
// 1. 键必须唯一
// 2. 快速查找(近似O(1))
// 3. 无序集合(但遍历顺序是稳定的)
2. 常用操作
// 添加和访问
scores.Add("Alice", 95); // 添加
scores["Bob"] = 87; // 添加或更新
// 安全访问
if (scores.TryGetValue("Alice", out int aliceScore))
{
// 找到Alice的分数
}
// 遍历
foreach (KeyValuePair<string, int> kvp in scores)
{
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
// 删除
scores.Remove("Alice"); // 删除指定键
scores.Clear(); // 清空所有
3. 性能优化
// 1. 预设容量(减少扩容)
var dict = new Dictionary<string, int>(1000);
// 2. 自定义比较器
var caseInsensitiveDict = new Dictionary<string, int>(
StringComparer.OrdinalIgnoreCase);
// 3. 避免频繁的ContainsKey检查
// 不推荐:
if (dict.ContainsKey(key)) { var value = dict[key]; }
// 推荐:
if (dict.TryGetValue(key, out var value)) { /* 使用value */ }
三、文件操作核心要点
1. 常见读取方式
// 1. 一次性读取(小文件)
string content = File.ReadAllText("file.txt");
// 2. 逐行读取(大文件)
foreach (string line in File.ReadLines("file.txt"))
{
// 逐行处理
}
// 3. 流式读取(完全控制)
using (var reader = new StreamReader("file.txt"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
// 处理每一行
}
}
// 4. 异步读取
string content = await File.ReadAllTextAsync("file.txt");
2. 重要注意事项
// 1. 总是使用using语句
// 错误:忘记释放资源
var reader = new StreamReader("file.txt");
// 正确:自动释放资源
using (var reader = new StreamReader("file.txt"))
{
// 处理文件
}
// 2. 异常处理
try
{
string content = File.ReadAllText("file.txt");
}
catch (FileNotFoundException ex)
{
Console.WriteLine($"文件不存在: {ex.Message}");
}
catch (IOException ex)
{
Console.WriteLine($"IO错误: {ex.Message}");
}
// 3. 路径处理
string fullPath = Path.Combine("folder", "subfolder", "file.txt");
string extension = Path.GetExtension(fullPath);
string fileName = Path.GetFileNameWithoutExtension(fullPath);
四、委托(Delegate)核心机制
1. 委托类型
// 1. 自定义委托(传统方式)
delegate void MyDelegate(string message);
// 2. 内置泛型委托(推荐)
Action<string> actionDelegate; // 无返回值
Func<string, int> funcDelegate; // 有返回值
Predicate<string> predicateDelegate;// 返回bool
// 3. 多播委托
Action multiDelegate = Method1;
multiDelegate += Method2; // 添加方法
multiDelegate -= Method1; // 移除方法
2. Lambda表达式
// Lambda表达式简化委托
Func<int, int, int> add = (a, b) => a + b;
Action<string> print = msg => Console.WriteLine(msg);
// 带语句块的Lambda
Func<int, int> factorial = n =>
{
int result = 1;
for (int i = 2; i <= n; i++)
result *= i;
return result;
};
3. 事件机制
// 标准事件模式
public class Publisher
{
// 1. 定义事件
public event EventHandler<MyEventArgs> MyEvent;
// 2. 触发事件的方法
protected virtual void OnMyEvent(MyEventArgs e)
{
// 线程安全的调用
MyEvent?.Invoke(this, e);
}
}
// 3. 事件参数类
public class MyEventArgs : EventArgs
{
public string Message { get; }
public MyEventArgs(string message) => Message = message;
}
五、四大技术的关联应用
1. 泛型集合与文件操作
// 读取CSV文件到泛型列表
public List<T> ReadCsv<T>(string filePath, Func<string[], T> converter)
{
var result = new List<T>();
foreach (var line in File.ReadLines(filePath).Skip(1))
{
var fields = line.Split(',');
result.Add(converter(fields));
}
return result;
}
2. 字典与委托结合
// 命令模式:字典存储命令处理器
var commandHandlers = new Dictionary<string, Action<string>>();
commandHandlers["save"] = data => SaveToFile(data);
commandHandlers["load"] = data => LoadFromFile(data);
// 执行命令
if (commandHandlers.TryGetValue(command, out var handler))
{
handler(data);
}
3. 配置读取综合示例
public class ConfigLoader
{
// 泛型方法读取配置
public T GetConfig<T>(string key, T defaultValue = default)
{
// 从文件读取配置
var lines = File.ReadAllLines("config.txt");
var configDict = lines
.Select(l => l.Split('='))
.Where(parts => parts.Length == 2)
.ToDictionary(parts => parts[0], parts => parts[1]);
// 尝试获取并转换
if (configDict.TryGetValue(key, out string value))
{
return (T)Convert.ChangeType(value, typeof(T));
}
return defaultValue;
}
}
六、最佳实践总结
| 技术 | 使用场景 | 注意事项 |
|---|---|---|
| 泛型 | 1. 集合类 2. 通用算法 3. 工厂模式 |
1. 合理使用约束 2. 避免过度泛化 3. 注意类型推断 |
| 字典 | 1. 快速查找 2. 缓存数据 3. 配置存储 |
1. 键的唯一性 2. 线程安全 3. 哈希碰撞 |
| 文件操作 | 1. 配置读取 2. 数据持久化 3. 日志记录 |
1. 资源释放 2. 异常处理 3. 编码问题 |
| 委托 | 1. 事件处理 2. 回调函数 3. LINQ查询 |
1. 内存泄漏 2. 线程安全 3. Lambda捕获 |
七、学习路径建议
-
初级阶段:掌握基本语法和使用场景
-
中级阶段:理解底层原理,能处理常见问题
-
高级阶段:熟练组合使用,进行性能优化
-
专家阶段:深入理解CLR实现,解决复杂问题
这四大技术是C#开发的基石,建议通过实际项目练习,逐步加深理解和应用能力。
更多推荐



所有评论(0)