1. C#第五次学习总结:从基础语法到实战应用
作为一名.NET开发者,我最近完成了C#语言的第五轮系统学习。这次学习让我对C#有了更深入的理解,特别是在异步编程、LINQ和性能优化等方面收获颇丰。本文将分享我的学习历程和关键收获,希望能给正在学习C#的朋友一些参考。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. C#核心语法精要
2.1 类型系统与变量声明
C#是强类型语言,其类型系统非常丰富。除了基本的值类型(int, double等)和引用类型(class, interface等),C#还支持以下几种特殊类型:
- 可空值类型:
int? nullableInt = null; - 匿名类型:
var person = new { Name = "John", Age = 30 }; - 动态类型:
dynamic dynamicVar = "hello";
在变量声明方面,我特别推荐使用var关键字,它能让代码更简洁,同时保持类型安全。但要注意,var只是编译时类型推断,运行时类型仍然是确定的。
2.2 面向对象特性深入
C#的面向对象特性非常完善,包括:
- 继承与多态:支持单继承,但可以通过接口实现多重继承的效果
- 抽象类与接口:理解
abstract class和interface的使用场景差异 - 访问修饰符:掌握
public、private、protected、internal和protected internal的区别
一个实际开发中的经验是:优先使用接口而非抽象类,因为接口更灵活,更容易进行单元测试。
3. 现代C#特性实践
3.1 异步编程模式
C#的异步编程模型(async/await)是现代应用开发的核心。关键点包括:
csharp复制public async Task<string> GetDataAsync()
{
using (var client = new HttpClient())
{
return await client.GetStringAsync("https://api.example.com/data");
}
}
注意事项:
- 避免
async void方法,除非是事件处理器 - 注意死锁问题,特别是在UI线程中使用
.Result或.Wait() - 使用
ConfigureAwait(false)可以提高库代码的性能
3.2 LINQ查询表达式
LINQ是C#最强大的特性之一,它统一了数据查询的方式:
csharp复制var results = from p in products
where p.Price > 100
orderby p.Name
select new { p.Name, p.Price };
实际开发中,我经常使用LINQ的链式方法语法,因为它更灵活:
csharp复制var expensiveProducts = products
.Where(p => p.Price > 100)
.OrderBy(p => p.Name)
.Select(p => new { p.Name, p.Price });
4. 性能优化与最佳实践
4.1 集合类型选择
不同的集合类型有不同的性能特征:
| 集合类型 | 插入性能 | 查找性能 | 适用场景 |
|---|---|---|---|
| List |
O(1) | O(n) | 随机访问频繁 |
| Dictionary<TKey,TValue> | O(1) | O(1) | 键值查找频繁 |
| HashSet |
O(1) | O(1) | 唯一性检查 |
| LinkedList |
O(1) | O(n) | 频繁插入删除 |
经验法则:大多数情况下List
4.2 字符串处理优化
字符串在C#中是不可变的,频繁拼接会导致性能问题:
csharp复制// 不好 - 每次拼接都创建新字符串
string result = "";
for (int i = 0; i < 100; i++) {
result += i.ToString();
}
// 好 - 使用StringBuilder
var sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.Append(i);
}
string result = sb.ToString();
5. 实际项目中的应用案例
5.1 数据访问层实现
在我的一个电商项目中,我这样实现了数据访问层:
csharp复制public class ProductRepository : IProductRepository
{
private readonly DbContext _context;
public ProductRepository(DbContext context)
{
_context = context;
}
public async Task<IEnumerable<Product>> GetFeaturedProductsAsync()
{
return await _context.Products
.Where(p => p.IsFeatured)
.OrderBy(p => p.Price)
.Take(10)
.ToListAsync();
}
}
关键点:
- 依赖注入DbContext
- 使用异步方法
- 利用LINQ构建查询
5.2 API控制器设计
在Web API项目中,我遵循以下原则:
- 保持控制器精简
- 业务逻辑放在服务层
- 使用ActionResult
返回类型
示例:
csharp复制[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpGet("featured")]
public async Task<ActionResult<IEnumerable<ProductDto>>> GetFeaturedProducts()
{
var products = await _productService.GetFeaturedProductsAsync();
return Ok(products);
}
}
6. 调试与异常处理技巧
6.1 异常处理最佳实践
异常处理是健壮代码的关键:
csharp复制try
{
// 可能抛出异常的代码
}
catch (SpecificException ex) when (ex.ErrorCode == 404)
{
// 处理特定错误码
}
catch (SpecificException ex)
{
// 处理其他SpecificException
Log.Error(ex, "操作失败");
throw; // 重新抛出原始异常
}
catch (Exception ex)
{
// 最后兜底
Log.Error(ex, "未知错误");
throw new CustomException("操作失败", ex);
}
finally
{
// 清理资源
}
重要原则:
- 不要吞掉异常(空的catch块)
- 使用异常过滤器(when子句)进行精细控制
- 记录完整的异常信息
6.2 调试技巧
Visual Studio提供了强大的调试工具:
- 条件断点:右键断点→条件
- 即时窗口:调试时查看和修改变量
- 诊断工具:分析内存和CPU使用
- 远程调试:调试部署在服务器上的应用
一个有用的技巧是使用DebuggerDisplayAttribute自定义调试时对象的显示方式:
csharp复制[DebuggerDisplay("{Name} (ID: {Id})")]
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
7. 单元测试与TDD实践
7.1 编写有效的单元测试
使用xUnit框架的示例:
csharp复制public class CalculatorTests
{
[Theory]
[InlineData(1, 2, 3)]
[InlineData(-1, 1, 0)]
public void Add_ShouldReturnCorrectSum(int a, int b, int expected)
{
// Arrange
var calculator = new Calculator();
// Act
var result = calculator.Add(a, b);
// Assert
Assert.Equal(expected, result);
}
}
测试原则:
- 每个测试只验证一件事
- 测试名称应明确表达意图
- 避免测试中有逻辑(if/for等)
7.2 模拟依赖项
使用Moq框架模拟依赖:
csharp复制[Fact]
public void GetFeaturedProducts_ShouldReturnProducts()
{
// Arrange
var mockRepo = new Mock<IProductRepository>();
mockRepo.Setup(repo => repo.GetFeaturedProducts())
.Returns(new List<Product> { new Product { Id = 1, Name = "Test" } });
var service = new ProductService(mockRepo.Object);
// Act
var result = service.GetFeaturedProducts();
// Assert
Assert.Single(result);
Assert.Equal("Test", result.First().Name);
}
8. 高级主题与未来学习方向
8.1 反射与动态编程
C#的反射API允许在运行时检查类型信息:
csharp复制Type type = typeof(Product);
PropertyInfo[] properties = type.GetProperties();
foreach (var prop in properties)
{
Console.WriteLine($"{prop.Name} ({prop.PropertyType.Name})");
}
虽然强大,但反射性能较差,应谨慎使用。在.NET Core中,可以考虑使用源生成器(Source Generators)作为替代方案。
8.2 跨平台开发
随着.NET 5+的统一,C#现在可以用于:
- Web开发(ASP.NET Core)
- 移动开发(MAUI)
- 桌面开发(WPF, WinForms, Avalonia)
- 云原生应用
- 游戏开发(Unity)
我计划下一步深入学习ASP.NET Core的微服务架构和Blazor WebAssembly框架。
