csharp
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseC# 12 - Quick Reference
C# 12 - 快速参考
Deep Knowledge: Usewith technology:mcp__documentation__fetch_docsfor comprehensive documentation.csharp
深度知识:调用并指定技术为mcp__documentation__fetch_docs即可获取完整文档。csharp
Records
记录(Records)
csharp
// Positional record (immutable)
public record UserDto(int Id, string Name, string Email);
// Record with additional members
public record OrderDto(int Id, decimal Total)
{
public string FormattedTotal => Total.ToString("C");
}
// Record struct (value type, C# 10)
public readonly record struct Point(double X, double Y);
// With-expression (non-destructive mutation)
var updated = user with { Name = "New Name" };csharp
// Positional record (immutable)
public record UserDto(int Id, string Name, string Email);
// Record with additional members
public record OrderDto(int Id, decimal Total)
{
public string FormattedTotal => Total.ToString("C");
}
// Record struct (value type, C# 10)
public readonly record struct Point(double X, double Y);
// With-expression (non-destructive mutation)
var updated = user with { Name = "New Name" };Pattern Matching (C# 12)
模式匹配(C# 12)
csharp
// Switch expression
string GetDiscount(Customer customer) => customer switch
{
{ Type: CustomerType.Premium, YearsActive: > 5 } => "30%",
{ Type: CustomerType.Premium } => "20%",
{ Type: CustomerType.Regular, YearsActive: > 3 } => "10%",
_ => "0%",
};
// List patterns (C# 11)
var result = numbers switch
{
[1, 2, 3] => "exact match",
[1, .., 3] => "starts with 1, ends with 3",
[_, > 5, ..] => "second element > 5",
[] => "empty",
_ => "other",
};
// Type pattern with when
if (shape is Circle { Radius: > 10 } circle)
{
Console.WriteLine($"Large circle: {circle.Radius}");
}csharp
// Switch expression
string GetDiscount(Customer customer) => customer switch
{
{ Type: CustomerType.Premium, YearsActive: > 5 } => "30%",
{ Type: CustomerType.Premium } => "20%",
{ Type: CustomerType.Regular, YearsActive: > 3 } => "10%",
_ => "0%",
};
// List patterns (C# 11)
var result = numbers switch
{
[1, 2, 3] => "exact match",
[1, .., 3] => "starts with 1, ends with 3",
[_, > 5, ..] => "second element > 5",
[] => "empty",
_ => "other",
};
// Type pattern with when
if (shape is Circle { Radius: > 10 } circle)
{
Console.WriteLine($"Large circle: {circle.Radius}");
}Nullable Reference Types
可空引用类型
csharp
// Enable in .csproj: <Nullable>enable</Nullable>
public class UserService
{
// Nullable return type
public User? FindById(int id) => _users.FirstOrDefault(u => u.Id == id);
// Non-nullable parameter
public void Update(User user)
{
ArgumentNullException.ThrowIfNull(user);
// user is guaranteed non-null here
}
// Null-conditional and coalescing
public string GetDisplayName(User? user)
=> user?.Name ?? "Unknown";
// Required members (C# 11)
public required string Name { get; init; }
}csharp
// Enable in .csproj: <Nullable>enable</Nullable>
public class UserService
{
// Nullable return type
public User? FindById(int id) => _users.FirstOrDefault(u => u.Id == id);
// Non-nullable parameter
public void Update(User user)
{
ArgumentNullException.ThrowIfNull(user);
// user is guaranteed non-null here
}
// Null-conditional and coalescing
public string GetDisplayName(User? user)
=> user?.Name ?? "Unknown";
// Required members (C# 11)
public required string Name { get; init; }
}Async/Await Patterns
Async/Await 模式
csharp
// Basic async method
public async Task<User> GetUserAsync(int id)
{
var user = await _repository.FindAsync(id);
return user ?? throw new NotFoundException($"User {id} not found");
}
// Parallel async
public async Task<(User[], Order[])> GetDashboardDataAsync(int userId)
{
var usersTask = _userService.GetAllAsync();
var ordersTask = _orderService.GetByUserAsync(userId);
await Task.WhenAll(usersTask, ordersTask);
return (usersTask.Result, ordersTask.Result);
}
// IAsyncEnumerable
public async IAsyncEnumerable<User> GetUsersStreamAsync(
[EnumeratorCancellation] CancellationToken ct = default)
{
await foreach (var user in _context.Users.AsAsyncEnumerable().WithCancellation(ct))
{
yield return user;
}
}
// ValueTask for hot paths
public ValueTask<User?> GetCachedUserAsync(int id)
{
if (_cache.TryGetValue(id, out var user))
return ValueTask.FromResult<User?>(user);
return new ValueTask<User?>(LoadUserAsync(id));
}csharp
// Basic async method
public async Task<User> GetUserAsync(int id)
{
var user = await _repository.FindAsync(id);
return user ?? throw new NotFoundException($"User {id} not found");
}
// Parallel async
public async Task<(User[], Order[])> GetDashboardDataAsync(int userId)
{
var usersTask = _userService.GetAllAsync();
var ordersTask = _orderService.GetByUserAsync(userId);
await Task.WhenAll(usersTask, ordersTask);
return (usersTask.Result, ordersTask.Result);
}
// IAsyncEnumerable
public async IAsyncEnumerable<User> GetUsersStreamAsync(
[EnumeratorCancellation] CancellationToken ct = default)
{
await foreach (var user in _context.Users.AsAsyncEnumerable().WithCancellation(ct))
{
yield return user;
}
}
// ValueTask for hot paths
public ValueTask<User?> GetCachedUserAsync(int id)
{
if (_cache.TryGetValue(id, out var user))
return ValueTask.FromResult<User?>(user);
return new ValueTask<User?>(LoadUserAsync(id));
}LINQ
LINQ
csharp
// Method syntax (preferred)
var result = users
.Where(u => u.IsActive)
.OrderBy(u => u.Name)
.Select(u => new { u.Name, u.Email })
.ToList();
// GroupBy
var grouped = orders
.GroupBy(o => o.Status)
.Select(g => new { Status = g.Key, Count = g.Count(), Total = g.Sum(o => o.Amount) });
// Aggregate
var summary = orders.Aggregate(
new { Count = 0, Total = 0m },
(acc, order) => new { Count = acc.Count + 1, Total = acc.Total + order.Amount });
// Chunk (C# 12 / .NET 8)
var batches = users.Chunk(100); // IEnumerable<User[]>csharp
// Method syntax (preferred)
var result = users
.Where(u => u.IsActive)
.OrderBy(u => u.Name)
.Select(u => new { u.Name, u.Email })
.ToList();
// GroupBy
var grouped = orders
.GroupBy(o => o.Status)
.Select(g => new { Status = g.Key, Count = g.Count(), Total = g.Sum(o => o.Amount) });
// Aggregate
var summary = orders.Aggregate(
new { Count = 0, Total = 0m },
(acc, order) => new { Count = acc.Count + 1, Total = acc.Total + order.Amount });
// Chunk (C# 12 / .NET 8)
var batches = users.Chunk(100); // IEnumerable<User[]>Primary Constructors (C# 12)
主构造函数(C# 12)
csharp
// Class primary constructor
public class UserService(IUserRepository repository, ILogger<UserService> logger)
{
public async Task<User> GetByIdAsync(int id)
{
logger.LogInformation("Getting user {Id}", id);
return await repository.GetByIdAsync(id)
?? throw new NotFoundException($"User {id} not found");
}
}
// Record primary constructor (already existed)
public record UserDto(int Id, string Name, string Email);csharp
// Class primary constructor
public class UserService(IUserRepository repository, ILogger<UserService> logger)
{
public async Task<User> GetByIdAsync(int id)
{
logger.LogInformation("Getting user {Id}", id);
return await repository.GetByIdAsync(id)
?? throw new NotFoundException($"User {id} not found");
}
}
// Record primary constructor (already existed)
public record UserDto(int Id, string Name, string Email);Collection Expressions (C# 12)
集合表达式(C# 12)
csharp
// Array
int[] numbers = [1, 2, 3, 4, 5];
// List
List<string> names = ["Alice", "Bob", "Charlie"];
// Spread
int[] first = [1, 2, 3];
int[] second = [4, 5, 6];
int[] combined = [..first, ..second]; // [1, 2, 3, 4, 5, 6]csharp
// Array
int[] numbers = [1, 2, 3, 4, 5];
// List
List<string> names = ["Alice", "Bob", "Charlie"];
// Spread
int[] first = [1, 2, 3];
int[] second = [4, 5, 6];
int[] combined = [..first, ..second]; // [1, 2, 3, 4, 5, 6]Anti-Patterns
反模式
| Anti-Pattern | Why It's Bad | Correct Approach |
|---|---|---|
| Deadlocks | Use |
| Exceptions lost | Use |
| Mutable DTOs | Unexpected mutations | Use |
| No null checking | NullReferenceException | Enable nullable references |
| String concatenation in loops | Memory pressure | Use |
| 反模式 | 问题原因 | 正确做法 |
|---|---|---|
| 会导致死锁 | 使用 |
| 会丢失异常信息 | 使用 |
| 可变 DTO | 会出现非预期的修改 | 使用 |
| 没有空值检查 | 会抛出 NullReferenceException | 启用可空引用类型 |
| 循环中拼接字符串 | 内存占用过高 | 使用 |
Quick Troubleshooting
快速问题排查
| Issue | Likely Cause | Solution |
|---|---|---|
| Nullable warning | Missing null check | Add |
| Deadlock | | Use |
| LINQ multiple enumeration | Iterating IEnumerable twice | Call |
| Record equality fails | Reference type property | Override |
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 可空警告 | 缺少空值检查 | 添加 |
| 死锁 | async 上下文中使用了 | 使用 |
| LINQ 多次枚举 | 两次遍历了 IEnumerable | 先调用 |
| 记录相等性判断失败 | 使用了引用类型属性 | 重写 |