一、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秒)
// 异步数据加载完成
// 数据加载结束
网硕互联帮助中心



评论前必须登录!
注册