面向对象编程核心概念总结
一、类 vs 对象
| 概念 | 说明 | 类比 |
|---|---|---|
| 类 (Class) | 蓝图/模板,定义属性和方法 | 建筑设计图纸 |
| 对象 (Object) | 类的实例,有具体数据 | 按图纸建好的房子 |
| 实例化 | 从类创建对象的过程 | 按图纸施工 |
csharp
// 定义类(蓝图) public class People { // 类的成员 } // 创建对象(实例) People zhangsan = new People(); // 实例化二、类的三大成员
1.字段 (Field)
csharp
private int age; // 私有字段,类内部访问 protected int id; // 受保护字段,继承类访问 public string name; // 公有字段(不推荐)
特点:存储数据,通常私有,以小写字母开头
2.属性 (Property)
csharp
public string Name { get; set; } // 自动属性特点:控制字段访问,提供get/set方法,以大写字母开头
3.方法 (Method)
csharp
public void Eat() { Console.WriteLine("吃炸鸡"); }特点:定义行为,执行操作
三、访问修饰符
| 修饰符 | 访问范围 | 常用场景 |
|---|---|---|
| public | 任何地方 | 属性、公共方法 |
| private | 本类内部 | 字段(默认) |
| protected | 本类及子类 | 受保护成员 |
| internal | 当前程序集 | 类(默认) |
csharp
public class People { private int age; // ✅ 私有:数据安全 public string Name { get; set; } // ✅ 公有:外部访问 protected int id; // ⚠️ 保护:继承可用 public void Eat() { } // ✅ 公有:外部调用 }四、对象创建和使用
创建对象:
csharp
// 语法:类名 对象名 = new 类名(); People person = new People(); // 设置属性 person.Name = "张三"; // 调用方法 person.Eat();
五、代码执行流程
csharp
// 1. 定义类(编译时) public class People { public string Name { get; set; } public void Eat() { Console.WriteLine("吃炸鸡"); } } // 2. Main方法执行(运行时) static void Main(string[] args) { // 3. 创建对象(内存分配) People zhangsan = new People(); // 4. 设置属性 zhangsan.Name = "李四"; // 实际:zhangsan.Name.set("李四") // 5. 调用方法 zhangsan.Eat(); // 输出:吃炸鸡 // 6. 对象生命周期结束(垃圾回收) }六、实际应用示例
示例1:学生管理系统
csharp
public class Student { // 字段(私有) private string studentId; // 属性(公有) public string Name { get; set; } public int Age { get; set; } public double Score { get; set; } // 方法 public void Study(string subject) { Console.WriteLine($"{Name}正在学习{subject}"); } public bool IsPass() { return Score >= 60; } } // 使用 Student stu = new Student(); stu.Name = "张三"; stu.Age = 20; stu.Score = 85; stu.Study("数学"); Console.WriteLine($"是否及格: {stu.IsPass()}");示例2:购物车系统
csharp
public class ShoppingCart { private List<string> items = new List<string>(); // 私有字段 // 公有方法 public void AddItem(string item) { items.Add(item); Console.WriteLine($"已添加: {item}"); } public void ShowItems() { Console.WriteLine("购物车商品:"); foreach (var item in items) { Console.WriteLine($"- {item}"); } } }七、最佳实践
1.封装原则
csharp
// ❌ 不好:字段公有 public class BadExample { public int age; // 外部可以直接修改,不安全 } // ✅ 好:字段私有,属性公有 public class GoodExample { private int age; // 私有字段 public int Age // 公有属性 { get { return age; } set { if (value >= 0 && value <= 150) // 添加验证 age = value; } } }2.命名规范
csharp
public class Person { // 字段:_camelCase 或 camelCase private string _firstName; private int age; // 属性:PascalCase public string FirstName { get; set; } // 方法:PascalCase public void DisplayInfo() { } }3.初始化建议
csharp
// 方式1:默认构造函数 + 属性设置 People p1 = new People(); p1.Name = "张三"; // 方式2:构造函数初始化 public class People { public People(string name) { Name = name; } } People p2 = new People("李四"); // 方式3:对象初始化器(C# 3.0+) People p3 = new People { Name = "王五", Age = 25 };八、常见错误
❌ 错误1:混淆类和对象
csharp
// 错误:试图使用类调用实例方法 People.Eat(); // ❌ 编译错误 // 正确:必须先创建对象 People person = new People(); person.Eat(); // ✅
❌ 错误2:访问私有字段
csharp
People person = new People(); person.age = 20; // ❌ 编译错误:age是私有的 person.Name = "张三"; // ✅ Name属性是公有的
❌ 错误3:忘记实例化
csharp
People person; // 只声明,未实例化 person.Name = "张三"; // ❌ 运行时NullReferenceException People person = new People(); // ✅ 正确实例化 person.Name = "张三"; // ✅
九、扩展概念
1.静态 vs 实例成员
csharp
public class Calculator { // 实例成员:需要对象 public int Add(int a, int b) { return a + b; } // 静态成员:直接通过类访问 public static int Multiply(int a, int b) { return a * b; } } // 使用 Calculator calc = new Calculator(); int sum = calc.Add(1, 2); // 需要对象 int product = Calculator.Multiply(3, 4); // 直接类访问2.构造函数
csharp
public class Person { public string Name { get; set; } // 默认构造函数 public Person() { } // 带参数构造函数 public Person(string name) { Name = name; } }十、一句话总结
类是模板,对象是实例。字段存数据要私有,属性控访问要公有,方法定行为可调用。用new创建对象,用.访问成员。记住:先有类蓝图,再有对象实例。
C# 冒泡排序 & 选择排序 核心知识点极简总结
一、冒泡排序(Bubble Sort)
核心逻辑
重复遍历数组,相邻元素两两比较交换,每轮将最大 / 最小元素 “冒泡” 到数组末尾,共需n-1轮遍历(n 为数组长度)。
核心特点
| 维度 | 说明 |
|---|---|
| 时间复杂度 | 平均 / 最坏 O (n²),最好(已排序)O (n) |
| 空间复杂度 | O (1)(原地排序) |
| 排序性质 | 稳定排序(相等元素相对位置不变) |
| 核心优势 | 逻辑简单,可提前终止(优化版) |
| 核心劣势 | 交换次数多,大数据量效率低 |
极简代码(升序)
csharp
运行
void BubbleSort(int[] arr) { for (int i = 0; i < arr.Length - 1; i++) { bool swapped = false; // 优化:无交换则提前结束 for (int j = 0; j < arr.Length - 1 - i; j++) { if (arr[j] > arr[j+1]) { // 相邻比较,逆序则交换 (arr[j], arr[j+1]) = (arr[j+1], arr[j]); // C# 元组交换 swapped = true; } } if (!swapped) break; } }二、选择排序(Selection Sort)
核心逻辑
分 “已排序区” 和 “未排序区”,每轮遍历未排序区找到最小 / 最大元素,仅 1 次交换到已排序区末尾,共需n-1轮。
核心特点
| 维度 | 说明 |
|---|---|
| 时间复杂度 | 所有情况 O (n²)(必遍历完所有轮次) |
| 空间复杂度 | O (1)(原地排序) |
| 排序性质 | 不稳定排序(相等元素可能交换位置) |
| 核心优势 | 交换次数少(每轮最多 1 次) |
| 核心劣势 | 效率固定,无优化空间 |
极简代码(升序)
csharp
运行
void SelectionSort(int[] arr) { for (int i = 0; i < arr.Length - 1; i++) { int minIndex = i; // 记录未排序区最小值索引 for (int j = i + 1; j < arr.Length; j++) { if (arr[j] < arr[minIndex]) minIndex = j; } if (minIndex != i) { // 找到更小值才交换 (arr[i], arr[minIndex]) = (arr[minIndex], arr[i]); } } }三、核心对比(C# 视角)
| 特性 | 冒泡排序 | 选择排序 |
|---|---|---|
| 交换次数 | 多(相邻逆序就交换) | 少(每轮仅 1 次) |
| 稳定性 | 稳定 | 不稳定 |
| 优化空间 | 可提前终止(无交换则 break) | 无 |
| 适用场景 | 小数据量、近乎有序数组 | 小数据量、对交换次数敏感 |
总结
- 两者均为基础排序,仅适用于小数据量场景;
- 冒泡胜在 “稳定 + 可优化”,选择胜在 “交换少”;
- C# 中可通过元组
(a,b)=(b,a)简化交换逻辑,无需临时变量。
C# var、dynamic 对比
一、var vs dynamic 核心对比
| 特性 | var | dynamic |
|---|---|---|
| 类型确定时机 | 编译期(静态类型) | 运行期(动态类型) |
| 类型推导 | 由初始化值推导,不可更改 | 无固定类型,运行时动态绑定 |
| 编译检查 | 有(语法 / 类型错误编译报错) | 无(错误仅运行时暴露) |
| IntelliSense | 支持(编译器已知类型) | 不支持(无编译期类型提示) |
| 适用场景 | 简化冗长类型声明(如 LINQ) | 动态交互(COM/JSON/ 动态语言) |
| 核心示例 | var list = new List<int>(); | dynamic obj = 10; obj = "abc"; |
关键补充(C# 视角)
- var:本质是 “语法糖”,编译后会替换为实际类型,性能无损耗;必须初始化(
var a;报错)。 - dynamic:依赖 DLR(动态语言运行时),运行时解析成员,性能略低;可延迟初始化。
C# 字典用法极简总结
一、一句话核心
字典是键值对集合,通过键快速查找值,键必须唯一。
二、基本操作(记住这5个就够用)
1.创建字典
csharp
Dictionary<string, int> dict = new Dictionary<string, int>();
2.添加数据
csharp
dict.Add("苹果", 5); // 方法1 dict["香蕉"] = 3; // 方法2(更常用)3.获取数据
csharp
int count = dict["苹果"]; // 直接取(键必须存在)
4.安全获取(推荐!)
csharp
if (dict.TryGetValue("苹果", out int value)) { Console.WriteLine(value); // 5 }5.检查键是否存在
csharp
if (dict.ContainsKey("苹果")) { // 存在 }三、遍历字典(3种方式)
csharp
Dictionary<string, int> scores = new Dictionary<string, int> { {"张三", 85}, {"李四", 92} }; // 方式1:遍历键值对(最常用) foreach (KeyValuePair<string, int> pair in scores) { Console.WriteLine($"{pair.Key}: {pair.Value}"); } // 方式2:只遍历键 foreach (string name in scores.Keys) { Console.WriteLine(name); } // 方式3:只遍历值 foreach (int score in scores.Values) { Console.WriteLine(score); }