云计算百科
云计算领域专业知识百科平台

C#核心知识点系统梳理:从基础到进阶

一、C# 基础语法

1. 变量与类型

  • 变量:程序中存储数据的容器,声明格式:类型 变量名 [= 初始值];
  • 基本类型:C#是强类型语言,变量必须指定类型,核心内置类型如下:
类型说明示例
int 整数(32位) int age = 20;
string 字符串 string name = "张三";
double 双精度浮点数 double score = 95.5;
bool 布尔值(true/false) bool isPass = true;
char 单个字符 char c = 'A';

示例代码:

// 变量声明与赋值
int num1 = 10;
int num2; // 先声明,后赋值
num2 = 20;
double pi = 3.1415926;
bool isStudent = false;

2. 字符串

字符串是string类型(引用类型),C#提供丰富的字符串操作方法:

核心操作示例:

string str1 = "Hello";
string str2 = "World";

// 拼接
string str3 = str1 + " " + str2; // Hello World
string str4 = string.Format("{0} {1}", str1, str2); // 格式化拼接
string str5 = $"{str1} {str2}"; // 插值拼接(推荐)

// 常用方法
bool isEmpty = string.IsNullOrEmpty(str1); // 判断是否为空/Null
int length = str1.Length; // 获取长度:5
string upperStr = str1.ToUpper(); // 转大写:HELLO
string subStr = str3.Substring(0, 5); // 截取子串:Hello
bool contains = str3.Contains("World"); // 是否包含:true

3. 数组

数组是固定长度的同类型数据集合,声明格式:类型[] 数组名 = new 类型[长度];

示例代码:

// 数组声明与初始化
int[] nums1 = new int[3]; // 长度为3的int数组,默认值0
nums1[0] = 1;
nums1[1] = 2;
nums1[2] = 3;

int[] nums2 = { 10, 20, 30 }; // 直接初始化(长度自动为3)

// 遍历数组
for (int i = 0; i < nums2.Length; i++)
{
Console.WriteLine(nums2[i]); // 输出10、20、30
}

// 增强for循环
foreach (int num in nums2)
{
Console.WriteLine(num);
}

4. 集合 List、Dictionary

数组长度固定,集合是动态长度的容器,更常用:

  • List:动态数组,存储同类型元素,可增删改查;
  • Dictionary<K, V>:键值对集合,通过唯一键(K)查找值(V)。

示例代码:

// List<T> 示例
List<string> names = new List<string>();
names.Add("张三"); // 添加元素
names.Add("李四");
names.Remove("李四"); // 删除元素
names[0] = "王五"; // 修改元素

// 遍历List
foreach (string name in names)
{
Console.WriteLine(name); // 输出王五
}

// Dictionary<K, V> 示例
Dictionary<int, string> student = new Dictionary<int, string>();
student.Add(101, "张三"); // 添加键值对(键101,值张三)
student[102] = "李四"; // 另一种添加方式

// 遍历Dictionary
foreach (KeyValuePair<int, string> kv in student)
{
Console.WriteLine($"学号:{kv.Key},姓名:{kv.Value}");
}

// 通过键取值
string name101 = student[101]; // 张三

5. 循环、判断

(1)判断语句
  • if/else:条件判断;
  • switch:多分支判断。

示例:

int score = 85;
// if/else
if (score >= 90)
{
Console.WriteLine("优秀");
}
else if (score >= 80)
{
Console.WriteLine("良好");
}
else
{
Console.WriteLine("及格");
}

// switch
switch (score / 10)
{
case 9:
Console.WriteLine("优秀");
break;
case 8:
Console.WriteLine("良好");
break;
default:
Console.WriteLine("及格");
break;
}

(2)循环语句
  • for:已知循环次数;
  • while:未知循环次数,先判断后执行;
  • do-while:未知循环次数,先执行后判断;
  • foreach:遍历集合/数组。

示例:

// for循环
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i); // 0-4
}

// while循环
int j = 0;
while (j < 5)
{
Console.WriteLine(j); // 0-4
j++;
}

// do-while循环
int k = 0;
do
{
Console.WriteLine(k); // 0-4
k++;
} while (k < 5);

6. 异常 try-catch

捕获程序运行时的错误,避免程序崩溃,核心结构:try(可能出错的代码)+ catch(捕获异常)+ finally(无论是否出错都执行)。

示例代码:

try
{
int a = 10;
int b = 0;
int c = a / b; // 除数为0,抛出异常
}
catch (DivideByZeroException ex) // 捕获特定异常
{
Console.WriteLine($"错误:{ex.Message}"); // 输出异常信息
}
catch (Exception ex) // 捕获所有异常(兜底)
{
Console.WriteLine($"未知错误:{ex.Message}");
}
finally
{
Console.WriteLine("无论是否出错,我都会执行");
}

7. 命名空间、类、对象、构造函数

(1)命名空间(namespace)

用于组织代码,避免类名冲突,格式:namespace 命名空间名 { … },使用时需using 命名空间名;。

(2)类与对象
  • 类:数据和方法的集合,是对象的“模板”;
  • 对象:类的实例,通过new创建。
(3)构造函数

与类名相同、无返回值的方法,创建对象时自动执行,用于初始化对象属性。

示例代码:

// 命名空间
namespace MyApp
{
// 类
public class Person
{
// 字段
public string Name;
public int Age;

// 无参构造函数
public Person()
{
Name = "默认姓名";
Age = 0;
}

// 有参构造函数
public Person(string name, int age)
{
Name = name;
Age = age;
}

// 方法
public void SayHello()
{
Console.WriteLine($"大家好,我是{Name},今年{Age}岁");
}
}

class Program
{
static void Main(string[] args)
{
// 创建对象(调用无参构造)
Person p1 = new Person();
p1.SayHello(); // 输出:大家好,我是默认姓名,今年0岁

// 创建对象(调用有参构造)
Person p2 = new Person("张三", 20);
p2.SayHello(); // 输出:大家好,我是张三,今年20岁
}
}
}

8. 值类型 vs 引用类型

C#数据类型分为两类,核心区别是存储位置和赋值方式:

类型存储位置赋值方式示例
值类型 栈(Stack) 复制值(独立存储) int、bool、struct、enum
引用类型 堆(Heap) 复制引用(指向同一对象) string、数组、类、List、Dictionary

示例代码:

// 值类型示例
int a = 10;
int b = a; // 复制值,b=10
b = 20;
Console.WriteLine(a); // 输出10(a不受b影响)

// 引用类型示例
List<int> list1 = new List<int>() { 1, 2 };
List<int> list2 = list1; // 复制引用,指向同一个List
list2.Add(3);
Console.WriteLine(list1.Count); // 输出3(list1被修改)

9. 枚举 enum、结构体 struct

(1)枚举(enum)

用于定义一组命名的常量,提高代码可读性。

示例:

// 定义枚举
enum WeekDay
{
Monday, // 默认值0
Tuesday, // 1
Wednesday // 2
}

// 使用枚举
WeekDay today = WeekDay.Tuesday;
if (today == WeekDay.Tuesday)
{
Console.WriteLine("今天是周二");
}
// 枚举转字符串
string dayStr = today.ToString(); // Tuesday
// 字符串转枚举
WeekDay day = (WeekDay)Enum.Parse(typeof(WeekDay), "Wednesday");

(2)结构体(struct)

轻量级的自定义值类型,适合存储少量数据(如坐标、颜色),与类的核心区别:struct是值类型,class是引用类型。

示例:

// 定义结构体
struct Point
{
public int X;
public int Y;

// 结构体构造函数(必须为所有字段赋值)
public Point(int x, int y)
{
X = x;
Y = y;
}

// 结构体方法
public void Show()
{
Console.WriteLine($"坐标:({X}, {Y})");
}
}

// 使用结构体
Point p = new Point(10, 20);
p.Show(); // 输出:坐标:(10, 20)


二、面向对象 OOP

1. 封装、继承、多态(OOP三大特性)

(1)封装

隐藏对象的内部实现细节,仅通过公开方法/属性暴露必要功能,核心是访问修饰符+属性。

示例:

public class Person
{
// 私有字段(隐藏细节)
private string _name;
private int _age;

// 公共属性(暴露访问接口,可添加校验逻辑)
public string Name
{
get { return _name; }
set { _name = value; }
}

public int Age
{
get { return _age; }
set
{
// 封装校验逻辑
if (value < 0 || value > 150)
throw new ArgumentException("年龄无效");
_age = value;
}
}

// 公共方法(暴露功能)
public void SayHello()
{
Console.WriteLine($"我是{_name},今年{_age}岁");
}
}

(2)继承

允许一个类(子类/派生类)继承另一个类(父类/基类)的属性和方法,实现代码复用,C#单继承(一个子类只能继承一个父类)。

示例:

// 父类
public class Animal
{
public string Name { get; set; }

public void Eat()
{
Console.WriteLine($"{Name}在吃东西");
}
}

// 子类(继承Animal)
public class Dog : Animal
{
// 子类特有方法
public void Bark()
{
Console.WriteLine($"{Name}在汪汪叫");
}
}

// 使用
Dog dog = new Dog();
dog.Name = "旺财";
dog.Eat(); // 继承父类方法:旺财在吃东西
dog.Bark(); // 子类特有方法:旺财在汪汪叫

(3)多态

同一行为在不同对象上有不同表现形式,核心实现方式:重写(override) + 抽象方法/虚方法。

示例:

// 父类(虚方法)
public class Animal
{
public string Name { get; set; }

// 虚方法:允许子类重写
public virtual void MakeSound()
{
Console.WriteLine($"{Name}发出声音");
}
}

// 子类1:重写虚方法
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine($"{Name}汪汪叫");
}
}

// 子类2:重写虚方法
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine($"{Name}喵喵叫");
}
}

// 多态调用
Animal animal1 = new Dog() { Name = "旺财" };
Animal animal2 = new Cat() { Name = "咪咪" };
animal1.MakeSound(); // 输出:旺财汪汪叫
animal2.MakeSound(); // 输出:咪咪喵喵叫

2. 访问修饰符

控制类/字段/方法的访问范围,核心修饰符:

修饰符访问范围
public 所有程序集都可访问
private 仅当前类内部可访问(默认)
protected 当前类 + 子类可访问
internal 仅当前程序集内可访问

3. 抽象类、接口 interface

(1)抽象类(abstract class)
  • 用abstract修饰,不能实例化;
  • 可包含抽象方法(无实现)和普通方法(有实现);
  • 子类必须重写抽象方法。

示例:

// 抽象类
public abstract class Shape
{
// 普通方法(有实现)
public void ShowInfo()
{
Console.WriteLine("这是一个图形");
}

// 抽象方法(无实现,子类必须重写)
public abstract double GetArea();
}

// 子类实现抽象类
public class Circle : Shape
{
public double Radius { get; set; }

// 重写抽象方法
public override double GetArea()
{
return Math.PI * Radius * Radius;
}
}

// 使用
Circle circle = new Circle() { Radius = 2 };
circle.ShowInfo(); // 继承普通方法
Console.WriteLine(circle.GetArea()); // 输出:12.566…

(2)接口(interface)
  • 用interface定义,是“行为契约”,仅包含方法/属性的声明(无实现);
  • 类可实现多个接口(弥补C#单继承);
  • 实现类必须实现接口的所有成员。

示例:

// 定义接口
public interface IFly
{
void Fly(); // 接口方法(默认public,不能加修饰符)
}

public interface ISwim
{
void Swim();
}

// 类实现多个接口
public class Duck : IFly, ISwim
{
// 实现IFly接口
public void Fly()
{
Console.WriteLine("鸭子飞");
}

// 实现ISwim接口
public void Swim()
{
Console.WriteLine("鸭子游");
}
}

// 使用
Duck duck = new Duck();
duck.Fly();
duck.Swim();

4. 属性 get/set、依赖注入

(1)属性 get/set

封装字段的访问,分为:

  • 普通属性:手动定义get/set;
  • 自动属性:简化写法(编译器自动生成私有字段)。

示例:

public class Person
{
// 自动属性(推荐)
public string Name { get; set; }

// 只读属性(仅get)
public int Id { get; } = 1001;

// 带私有set的属性(外部只能读,内部可写)
public int Age { get; private set; }

// 手动属性(自定义逻辑)
private string _email;
public string Email
{
get { return _email; }
set
{
if (!value.Contains("@"))
throw new ArgumentException("邮箱格式错误");
_email = value;
}
}

// 方法内修改私有set的属性
public void SetAge(int age)
{
Age = age;
}
}

(2)依赖注入(DI,入门级)

核心思想:“面向接口编程”,将类的依赖对象通过构造函数/属性传入,降低耦合。

示例:

// 定义接口(依赖抽象)
public interface ILog
{
void WriteLog(string message);
}

// 实现类1
public class FileLog : ILog
{
public void WriteLog(string message)
{
Console.WriteLine($"写入文件:{message}");
}
}

// 实现类2
public class ConsoleLog : ILog
{
public void WriteLog(string message)
{
Console.WriteLine($"控制台输出:{message}");
}
}

// 业务类(依赖ILog,而非具体实现)
public class UserService
{
private readonly ILog _log;

// 构造函数注入
public UserService(ILog log)
{
_log = log;
}

public void AddUser(string userName)
{
// 业务逻辑
Console.WriteLine($"添加用户:{userName}");
// 日志记录(依赖注入的ILog)
_log.WriteLog($"用户{userName}已添加");
}
}

// 使用
// 注入FileLog
UserService service1 = new UserService(new FileLog());
service1.AddUser("张三"); // 输出:添加用户:张三 + 写入文件:用户张三已添加

// 注入ConsoleLog
UserService service2 = new UserService(new ConsoleLog());
service2.AddUser("李四"); // 输出:添加用户:李四 + 控制台输出:用户李四已添加


三、C#进阶

1. 委托、事件

(1)委托(delegate)

本质是“方法的类型”,可以存储和调用方法(类似函数指针),定义格式:delegate 返回值 委托名(参数列表);

示例:

// 定义委托(匹配无返回值、单个string参数的方法)
public delegate void MyDelegate(string message);

// 定义匹配的方法
public static void ShowMessage(string msg)
{
Console.WriteLine($"消息:{msg}");
}

public static void LogMessage(string msg)
{
Console.WriteLine($"日志:{msg}");
}

// 使用委托
static void Main(string[] args)
{
// 委托绑定方法
MyDelegate del = ShowMessage;
del += LogMessage; // 绑定多个方法(多播委托)

// 调用委托(执行所有绑定的方法)
del("Hello World");
// 输出:
// 消息:Hello World
// 日志:Hello World

del -= ShowMessage; // 移除方法
del("Test"); // 仅输出:日志:Test
}

(2)事件(event)

基于委托的“消息通知机制”,是特殊的委托,限制了外部直接调用,只能在类内部触发。

示例:

// 定义委托
public delegate void NotifyHandler(string message);

// 定义包含事件的类
public class User
{
// 定义事件(基于委托)
public event NotifyHandler OnLogin;

// 登录方法(内部触发事件)
public void Login(string userName)
{
Console.WriteLine($"{userName}登录成功");
// 触发事件(仅类内部可调用)
OnLogin?.Invoke($"{userName}{DateTime.Now}登录");
}
}

// 使用事件
static void Main(string[] args)
{
User user = new User();
// 订阅事件
user.OnLogin += (msg) => Console.WriteLine($"日志记录:{msg}");
user.OnLogin += (msg) => Console.WriteLine($"邮件通知:{msg}");

// 调用登录方法,触发事件
user.Login("张三");
// 输出:
// 张三登录成功
// 日志记录:张三于2026-02-25 10:00:00登录
// 邮件通知:张三于2026-02-25 10:00:00登录
}

2. Lambda 表达式

简化委托/匿名方法的写法,格式:(参数) => 表达式/代码块,常用于LINQ、委托、事件。

示例:

// 1. 替代委托方法
MyDelegate del = (msg) => Console.WriteLine($"Lambda:{msg}");
del("Hello"); // 输出:Lambda:Hello

// 2. LINQ中使用(筛选List)
List<int> nums = new List<int>() { 1, 2, 3, 4, 5 };
var evenNums = nums.Where(n => n % 2 == 0); // 筛选偶数
foreach (int num in evenNums)
{
Console.WriteLine(num); // 输出2、4
}

// 3. 带代码块的Lambda
Action<string> action = (msg) =>
{
string upperMsg = msg.ToUpper();
Console.WriteLine(upperMsg);
};
action("test"); // 输出:TEST

3. 泛型

定义时不指定具体类型,使用时再指定,实现代码复用,避免装箱拆箱,核心:泛型类<T>、泛型方法<T>、泛型接口<T>。

示例:

// 泛型类
public class MyGeneric<T>
{
private T _data;

public MyGeneric(T data)
{
_data = data;
}

public T GetData()
{
return _data;
}
}

// 泛型方法
public static T Max<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) > 0 ? a : b;
}

// 使用
MyGeneric<int> intGeneric = new MyGeneric<int>(100);
Console.WriteLine(intGeneric.GetData()); // 100

MyGeneric<string> strGeneric = new MyGeneric<string>("Hello");
Console.WriteLine(strGeneric.GetData()); // Hello

int maxInt = Max(10, 20); // 20
string maxStr = Max("A", "B"); // B

4. Task/async/await 异步编程

解决同步编程阻塞UI/线程的问题,async标记方法为异步,await等待异步任务完成,Task表示异步操作。

示例:

// 异步方法(返回Task/Task<T>)
public static async Task<string> GetDataAsync()
{
// 模拟耗时操作(如网络请求)
await Task.Delay(2000); // 等待2秒,不阻塞线程
return "异步数据加载完成";
}

// 调用异步方法
static async void Main(string[] args)
{
Console.WriteLine("开始加载数据…");
// 等待异步方法完成
string result = await GetDataAsync();
Console.WriteLine(result);
Console.WriteLine("数据加载结束");

// 等待控制台关闭(避免程序直接退出)
Console.ReadLine();
}

// 输出顺序:
// 开始加载数据…
// (等待2秒)
// 异步数据加载完成
// 数据加载结束


总结

  • 基础语法核心:C#是强类型语言,变量/类型是基础;数组长度固定,List/Dictionary是动态集合;try-catch处理异常;值类型存栈、引用类型存堆;enum/struct是自定义值类型。
  • OOP核心:封装隐藏细节,继承复用代码,多态实现灵活调用;抽象类/接口是“抽象契约”,访问修饰符控制访问范围;依赖注入降低类耦合。
  • 进阶核心:委托是方法的“类型”,事件是受限的委托;Lambda简化委托/匿名方法;泛型实现类型无关的代码复用;async/await是异步编程的简洁写法,避免线程阻塞。
  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » C#核心知识点系统梳理:从基础到进阶
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!