DotNetGuide超全C#语法实战宝典
还在为C#语法细节而头疼?想要系统掌握从基础到高级的C#语法特性?本文为你带来DotNetGuide项目中精心整理的C#语法实战宝典,涵盖C# 12/13新特性、LINQ高级用法、迭代器模式、类型转换等核心知识点,每个知识点都配有完整可运行的代码示例!
📚 读完本文你将收获
- ✅ C# 12/13最新语法特性详解
- ✅ LINQ查询的完整实战指南
- ✅ yield迭代器的深度解析与应用
- ✅ const与readonly的精准区别
- ✅ as与is操作符的实战对比
- ✅ Dictionary集合的全面操作指南
- ✅ goto语句的合理使用场景
🚀 C# 12 新特性实战
集合表达式(Collection Expressions)
C# 12引入了简洁的集合初始化语法,让代码更加清晰易读:
// 创建数组
int[] array = [55, 99, 100, 33];
// 创建列表
List<string> list = ["one", "two", "three", "five", "追逐时光者"];
// 创建Span
Span<char> span = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'k'];
// 创建交错数组
int[][] two2D = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [88, 8, 9]];
// 使用展开操作符合并数组
int[] item0 = [88, 2, 3];
int[] item1 = [22, 5, 6];
int[] item2 = [7, 99, 9];
int[] totalList = [.. item0, .. item1, .. item2];
主构造函数(Primary Constructors)
简化类结构的定义,特别适用于DTO(Data Transfer Object)和值对象:
public class Person(string name, int age)
{
public string Name => name;
public int Age => age;
}
public readonly struct Distance(double dx, double dy)
{
public readonly double Magnitude { get; } = Math.Sqrt(dx * dx + dy * dy);
public readonly double Direction { get; } = Math.Atan2(dy, dx);
}
默认Lambda参数
public static void DefaultLambdaParameters()
{
Func<double, double> testcube = x => x * x * x;
Func<int, int, bool> testForEquality = (x, y) => x == y;
Func<int, string, bool> isTooLong = (int x, string s) => s.Length > x;
}
🔥 C# 13 新特性解析
params Span参数
public static void SpanDataPrint<T>(params Span<T> spans)
{
for (int i = 0; i < spans.Length; i++)
{
Console.WriteLine(spans[i]);
}
}
新的Lock类型
private System.Threading.Lock _newLock = new System.Threading.Lock();
public void LockTest()
{
lock (_newLock)
{
// 传统 lock 语法(优化版)
}
using (_newLock.EnterScope())
{
// 作用域自动释放(推荐写法)
}
}
隐式索引访问
public class Numbers
{
public int[] Datas { get; set; } = new int[8];
}
var countdown = new Numbers()
{
Datas =
{
[1] = 0,
[2] = 1,
[^3] = 2, // C# 13 新语法
[^4] = 3,
[^5] = 4
}
};
📊 const vs readonly 深度对比
| 特性 | const | readonly |
|---|---|---|
| 初始化时机 | 编译时 | 运行时 |
| 内存分配 | 静态内存 | 实例内存 |
| 可修改性 | 不可修改 | 构造函数中可修改 |
| 类型限制 | 基本类型和字符串 | 任何类型 |
| 使用场景 | 数学常数、配置值 | 运行时确定的常量 |
public class ConstAndReadonlyExercise
{
// const 编译时常量
public const int MaxCount = 0;
public const UserRole CurrentUserRole = UserRole.Admin;
// readonly 运行时常量
public readonly string _applicationName;
public ConstAndReadonlyExercise()
{
_applicationName = "HelloDotNetGuide_V2"; // 构造函数中初始化
}
}
🔄 yield 迭代器模式详解
基础用法对比
// 使用yield的迭代器方法
public static IEnumerable<int> GetNumbersWithYield()
{
for (int i = 0; i < 6; i++)
{
yield return i; // 按需生成
}
}
// 传统方法返回List
public static List<int> GetNumbersWithoutYield()
{
var numbers = new List<int>();
for (int i = 0; i < 6; i++)
{
numbers.Add(i); // 一次性生成所有
}
return numbers;
}
延迟加载实战
public static IEnumerable<int> GetEvenNumbers(int number)
{
for (int i = 1; i < number; i++)
{
Console.WriteLine($"生成中 {i}");
if (i % 2 == 0)
{
yield return i; // 只在需要时生成
}
}
}
yield break 提前终止
public static IEnumerable<int> TakeWhilePositive(IEnumerable<int> numbers)
{
foreach (int n in numbers)
{
if (n > 0)
{
yield return n;
}
else
{
yield break; // 遇到非正数立即终止
}
}
}
🎯 is 与 as 操作符精准使用
is 操作符 - 类型检查与模式匹配
public static void IsOperator()
{
string title = "Hello DotNetGuide";
// 基本类型检查
if (title is string)
{
Console.WriteLine("是 string 类型");
}
// null 检查
if (title is not null)
{
Console.WriteLine("不为 null");
}
// 模式匹配(声明变量)
object obj = "追逐时光者";
if (obj is string str)
{
Console.WriteLine($"字符串内容: {str}");
}
// 列表模式匹配
int[] fib = [1, 1, 2, 3, 5];
Console.WriteLine(fib is [1, _, 2, ..]); // true
Console.WriteLine(fib is [.., 3, 5]); // true
}
as 操作符 - 安全类型转换
public static void AsOperator()
{
object title = "Hello DotNetGuide";
// 安全转换为string
string str = title as string;
if (str != null)
{
Console.WriteLine("是 string 类型: " + str);
}
// 安全转换为可空int
int? num = title as int?;
if (num.HasValue)
{
Console.WriteLine("是 int 类型: " + num.Value);
}
// 接口转换
IEnumerable<int> numbers = new List<int>() { 10, 20, 30 };
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]); // 输出: 40
}
}
📋 Dictionary 操作完整指南
基础操作
Dictionary<int, string> studentDic = new Dictionary<int, string>();
// 添加元素
studentDic.Add(1, "大姚");
studentDic[4] = "Charlie"; // 索引器添加/更新
// 安全访问
if (studentDic.TryGetValue(5, out var getUserName))
{
Console.WriteLine($"UserName:{getUserName}");
}
// 删除元素
bool isRemoved = studentDic.Remove(3);
遍历方式对比
// 方式1:遍历KeyValuePair
foreach (KeyValuePair<int, string> student in studentDic)
{
Console.WriteLine($"ID: {student.Key}, Name: {student.Value}");
}
// 方式2:遍历Keys
foreach (var key in studentDic.Keys)
{
Console.WriteLine($"Key: {key}, Value: {studentDic[key]}");
}
// 方式3:遍历Values
foreach (var value in studentDic.Values)
{
Console.WriteLine($"Value: {value}");
}
🎪 LINQ 查询大全
.NET 9 新特性
// CountBy - 统计词频
var sourceText = "This is a test text. This is only a test.";
KeyValuePair<string, int> mostFrequentWord = sourceText
.Split([' ', '.', ','], StringSplitOptions.RemoveEmptyEntries)
.Select(word => word.ToLowerInvariant())
.CountBy(word => word)
.MaxBy(pair => pair.Value);
// AggregateBy - 分组聚合
(string id, int score)[] data = [("0", 88), ("1", 5), ("2", 4), ("1", 10)];
var aggregatedData = data.AggregateBy(
keySelector: entry => entry.id,
seed: 0,
(totalScore, curr) => totalScore + curr.score
);
LINQ 方法分类表
| 类别 | 方法 | 描述 |
|---|---|---|
| 过滤 | Where, OfType | 根据条件筛选元素 |
| 投影 | Select, SelectMany | 转换或展平集合 |
| 排序 | OrderBy, ThenBy | 升序或降序排列 |
| 分组 | GroupBy, ToLookup | 按键分组元素 |
| 连接 | Join, GroupJoin | 合并多个数据源 |
| 聚合 | Count, Sum, Average | 计算统计值 |
| 元素 | First, Last, Single | 获取特定元素 |
| 转换 | ToArray, ToList | 转换集合类型 |
| 集合 | Concat, Union, Intersect | 集合操作 |
复杂查询示例
// 多条件查询 + 分页
int pageNumber = 2;
int pageSize = 10;
var pagedUsers = students
.Where(s => s.ClassID == 101 && s.Courses.Any(c => c.CourseName == "数学"))
.OrderBy(s => s.StudentName)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();
// 左连接查询
var courseStudentGroups = courses.GroupJoin(
students.SelectMany(
student => student.Courses,
(student, course) => new { Student = student, Course = course }
),
course => course.CourseID,
studentCoursePair => studentCoursePair.Course.CourseID,
(course, matchedStudents) => new
{
CourseName = course.CourseName,
Students = matchedStudents
.Select(pair => pair.Student.StudentName)
.DefaultIfEmpty("(无学生)")
.ToList()
}
);
⚡ goto 语句的合理使用
适用场景:错误重试机制
public static void GotoRetryUseExample()
{
int retryCount = 0;
retryLogic:
try
{
// 模拟可能出错的操作
Random random = new Random();
int result = random.Next(0, 2);
if (result == 0) throw new Exception("Error occurred");
Console.WriteLine("操作成功,重试次数: " + retryCount);
}
catch (Exception ex)
{
retryCount++;
if (retryCount < 3)
{
Console.WriteLine("发生错误,重试中...");
goto retryLogic; // 跳转到重试逻辑
}
else
{
Console.WriteLine("达到最大重试次数");
return;
}
}
}
替代方案(推荐)
public static void NonGotoRetryUseExample()
{
int retryCount = 0;
while (retryCount < 3)
{
try
{
// 业务逻辑
break; // 成功则跳出循环
}
catch (Exception ex)
{
retryCount++;
Console.WriteLine("发生错误,重试中...");
}
}
if (retryCount == 3)
{
Console.WriteLine("达到最大重试次数");
}
}
🎯 实战建议与最佳实践
- 版本选择:优先使用C# 12/13新特性,但确保团队技术栈兼容性
- 性能考量:yield适合大数据集延迟加载,小数据集直接返回List
- 代码可读性:适度使用模式匹配,避免过度复杂的模式
- 错误处理:使用TryXXX模式避免异常,如TryGetValue、TryAdd
- 集合选择:根据需求选择合适的集合类型,Dictionary适合键值查询
📈 学习路线图
通过本实战宝典,你不仅掌握了C#语法的核心要点,更重要的是学会了如何在实际项目中应用这些知识。每个示例都来自真实的开发场景,可以直接应用到你的项目中。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



