专栏导航
← 上一篇:组织代码 - 方法/函数
← 第一篇:
更复杂的结构 - 类与对象
- 专栏导航
-
- 什么是面向对象编程(OOP)?
-
- [传统编程 vs 面向对象编程](#传统编程 vs 面向对象编程)
- 现实生活中的例子
- 面向对象的核心思想
- 为什么面向对象重要?
- 类和对象
- 定义一个简单的类
- 创建对象并使用其属性
- [实践:定义 Person 类并创建对象](#实践:定义 Person 类并创建对象)
- [实践:定义 Student 类](#实践:定义 Student 类)
- 访问修饰符
- 类的命名规范
- [属性 vs 字段](#属性 vs 字段)
- 对象数组
- 对象集合(List<T>)
-
- 为什么需要对象集合?
- [List<T> 基础](#List<T> 基础)
- [List<Person> 的常用操作](#List<Person> 的常用操作)
- [List<Person> 常用方法](#List<Person> 常用方法)
- [LINQ 方法(Where、GroupBy、OrderBy、Select)](#LINQ 方法(Where、GroupBy、OrderBy、Select))
-
- [Where - 筛选数据](#Where - 筛选数据)
- [OrderBy / OrderByDescending - 排序](#OrderBy / OrderByDescending - 排序)
- [Select - 转换数据](#Select - 转换数据)
- [GroupBy - 分组](#GroupBy - 分组)
- [组合使用 LINQ 方法](#组合使用 LINQ 方法)
- [LINQ 方法总结](#LINQ 方法总结)
- [LINQ 实践:统计学生成绩](#LINQ 实践:统计学生成绩)
- 实践:学生信息管理系统
- [对象数组 vs List<Person>](#对象数组 vs List<Person>)
- 何时使用?
- 本章总结
什么是面向对象编程(OOP)?
传统编程 vs 面向对象编程
传统编程(面向过程):
- 关注"怎么做"(步骤、流程)
- 数据和行为分离
- 适合简单任务
面向对象编程(OOP):
- 关注"谁来做"(对象)
- 数据和行为封装在一起
- 适合复杂系统
现实生活中的例子
想象你要描述一只猫:
面向过程:
猫的颜色 = 白色
猫的体重 = 5kg
猫吃鱼
猫睡觉
面向对象:
猫
├── 属性(特征)
│ ├── 颜色:白色
│ ├── 体重:5kg
│ └── 年龄:2岁
└── 方法(行为)
├── 吃鱼()
├── 睡觉()
└── 叫()
面向对象的核心思想
将现实世界中的事物抽象为对象 ,每个对象都有自己的属性 (特征)和方法(行为)。
为什么面向对象重要?
✅ 更接近现实 :代码结构和现实世界相似,易于理解
✅ 代码复用 :通过继承实现代码复用
✅ 易于维护 :修改一个类不影响其他部分
✅ 封装性好 :隐藏内部实现细节
✅ 可扩展性强:方便添加新功能
类和对象
类(Class)
类是对象的模板 或蓝图。
类比:
- 类 = 房屋设计图纸
- 对象 = 根据图纸建造的具体房子
对象(Object)
对象是根据类创建的实例。
类比:
图纸(类):住宅设计图
对象1:小明家的房子
对象2:小红家的房子
对象3:小刚家的房子
类与对象的关系
类(模板)
↓ 创建多个
对象1(实例)
对象2(实例)
对象3(实例)
...
定义一个简单的类
基本语法
csharp
class 类名
{
// 字段(属性)
访问修饰符 数据类型 字段名;
// 方法
访问修饰符 返回值类型 方法名()
{
// 方法体
}
}
示例:定义 Person 类
csharp
class Person
{
// 属性(字段)
public string Name; // 姓名
public int Age; // 年龄
public string Gender; // 性别
// 方法
public void Introduce()
{
Console.WriteLine($"大家好,我叫{Name},今年{Age}岁,性别{Gender}。");
}
}
代码解析
csharp
class Person
{
// 公开字段,可以从外部访问
public string Name; // 存储姓名
public int Age; // 存储年龄
public string Gender; // 存储性别
// 公开方法,可以被外部调用
public void Introduce() // 自我介绍的方法
{
// 使用字段输出信息
Console.WriteLine($"大家好,我叫{Name},今年{Age}岁,性别{Gender}。");
}
}
创建对象并使用其属性
创建对象
csharp
// 语法:类名 对象名 = new 类名();
Person person1 = new Person();
Person person2 = new Person();
访问和修改属性
csharp
Person person = new Person();
// 访问属性
Console.WriteLine(person.Name); // null(未赋值)
// 修改属性
person.Name = "张三";
person.Age = 25;
person.Gender = "男";
// 再次访问
Console.WriteLine(person.Name); // 张三
Console.WriteLine(person.Age); // 25
Console.WriteLine(person.Gender); // 男
调用对象的方法
csharp
Person person = new Person();
person.Name = "李四";
person.Age = 30;
person.Gender = "女";
// 调用方法
person.Introduce();
// 输出:大家好,我叫李四,今年30岁,性别女。
实践:定义 Person 类并创建对象
csharp
using System;
namespace Week7Practice
{
// 定义 Person 类
class Person
{
// 属性(字段)
public string Name;
public int Age;
public string Gender;
public string Occupation; // 职业
// 方法
public void Introduce()
{
Console.WriteLine($"大家好,我叫{Name},今年{Age}岁,性别{Gender}。");
Console.WriteLine($"我的职业是{Occupation}。");
}
public void SayHello()
{
Console.WriteLine($"{Name}向你问好:Hello!");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 创建对象 =====\n");
// 创建第一个 Person 对象
Person person1 = new Person();
person1.Name = "张三";
person1.Age = 28;
person1.Gender = "男";
person1.Occupation = "程序员";
Console.WriteLine("--- 第一个人 ---");
Console.WriteLine($"姓名:{person1.Name}");
Console.WriteLine($"年龄:{person1.Age}");
Console.WriteLine($"性别:{person1.Gender}");
Console.WriteLine($"职业:{person1.Occupation}");
person1.Introduce();
person1.SayHello();
Console.WriteLine();
// 创建第二个 Person 对象
Person person2 = new Person();
person2.Name = "李四";
person2.Age = 25;
person2.Gender = "女";
person2.Occupation = "设计师";
Console.WriteLine("--- 第二个人 ---");
Console.WriteLine($"姓名:{person2.Name}");
Console.WriteLine($"年龄:{person2.Age}");
Console.WriteLine($"性别:{person2.Gender}");
Console.WriteLine($"职业:{person2.Occupation}");
person2.Introduce();
person2.SayHello();
Console.WriteLine("\n===== 多个对象 =====");
Console.WriteLine($"当前创建了 {person1.Name} 和 {person2.Name} 两个对象");
}
}
}
输出:
===== 创建对象 =====
--- 第一个人 ---
姓名:张三
年龄:28
性别:男
职业:程序员
大家好,我叫张三,今年28岁,性别男。
我的职业是程序员。
张三向你问好:Hello!
--- 第二个人 ---
姓名:李四
年龄:25
性别:女
职业:设计师
大家好,我叫李四,今年25岁,性别女。
我的职业是设计师。
李四向你问好:Hello!
===== 多个对象 =====
当前创建了 张三 和 李四 两个对象
实践:定义 Student 类
csharp
using System;
namespace Week7Practice
{
// 定义 Student 类
class Student
{
// 属性
public string Name; // 姓名
public int Age; // 年龄
public string Grade; // 年级
public double Score; // 成绩
// 方法
public void PrintInfo()
{
Console.WriteLine($"学生信息:");
Console.WriteLine($" 姓名:{Name}");
Console.WriteLine($" 年龄:{Age}");
Console.WriteLine($" 年级:{Grade}");
Console.WriteLine($" 成绩:{Score}");
}
public bool IsPass()
{
return Score >= 60;
}
public void PrintGrade()
{
if (Score >= 90)
Console.WriteLine($"成绩等级:优秀");
else if (Score >= 80)
Console.WriteLine($"成绩等级:良好");
else if (Score >= 60)
Console.WriteLine($"成绩等级:及格");
else
Console.WriteLine($"成绩等级:不及格");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 学生信息管理 =====\n");
// 创建学生对象
Student student1 = new Student();
student1.Name = "小明";
student1.Age = 18;
student1.Grade = "高三";
student1.Score = 92.5;
Student student2 = new Student();
student2.Name = "小红";
student2.Age = 17;
student2.Grade = "高二";
student2.Score = 58.0;
// 显示学生信息
Console.WriteLine("--- 学生1 ---");
student1.PrintInfo();
student1.PrintGrade();
Console.WriteLine($"是否及格:{(student1.IsPass() ? "是" : "否")}");
Console.WriteLine();
Console.WriteLine("--- 学生2 ---");
student2.PrintInfo();
student2.PrintGrade();
Console.WriteLine($"是否及格:{(student2.IsPass() ? "是" : "否")}");
// 计算平均分
double average = (student1.Score + student2.Score) / 2;
Console.WriteLine($"\n两人平均分:{average:F2}");
}
}
}
输出:
===== 学生信息管理 =====
--- 学生1 ---
学生信息:
姓名:小明
年龄:18
年级:高三
成绩:92.5
成绩等级:优秀
是否及格:是
--- 学生2 ---
学生信息:
姓名:小红
年龄:17
年级:高二
成绩:58
成绩等级:不及格
是否及格:否
两人平均分:75.25
访问修饰符
访问修饰符控制类成员的可访问性。
常用访问修饰符
| 修饰符 | 说明 | 可访问性 |
|---|---|---|
public |
公开 | 可以从任何地方访问 |
private |
私有 | 只能在当前类内部访问 |
protected |
受保护 | 只能在当前类和子类中访问 |
internal |
内部 | 只能在同一程序集中访问 |
示例
csharp
class Person
{
public string Name; // 公开,可以外部访问
private int Age; // 私有,只能内部访问
public void SetAge(int age)
{
// 可以访问私有字段
if (age >= 0 && age <= 150)
{
Age = age; // 正确
}
}
public int GetAge()
{
return Age; // 正确
}
}
class Program
{
static void Main()
{
Person person = new Person();
person.Name = "张三"; // 正确,public
// person.Age = 25; // 错误!private 不能外部访问
person.SetAge(25); // 正确,通过公开方法访问
Console.WriteLine(person.GetAge());
}
}
类的命名规范
✅ 推荐:
- 使用名词或名词短语
- 帕斯卡命名法(首字母大写)
- 单数形式
csharp
Person, Student, Car, Book
UserProfile, OrderItem, ShoppingCart
❌ 不推荐:
csharp
person, student // 应该用大写开头
Persons, Students // 应该用单数
DoSomething // 应该是名词,不是动词
属性 vs 字段
字段(Field)
csharp
class Person
{
public string Name; // 字段(field)
}
属性(Property)
属性是字段的封装,可以添加验证逻辑。
csharp
class Person
{
private string name; // 私有字段
// 属性
public string Name
{
get { return name; }
set
{
if (!string.IsNullOrEmpty(value))
{
name = value;
}
}
}
}
简化写法(自动属性):
csharp
class Person
{
public string Name { get; set; } // 自动属性
public int Age { get; set; }
}
使用属性
csharp
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person person = new Person();
person.Name = "张三"; // set
Console.WriteLine(person.Name); // get
实践:带验证的属性
csharp
class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value >= 0 && value <= 150)
{
age = value;
}
else
{
Console.WriteLine("年龄必须在 0-150 之间!");
}
}
}
}
Person person = new Person();
person.Age = 25; // 正常赋值
person.Age = 200; // 输出:年龄必须在 0-150 之间!
Console.WriteLine(person.Age); // 输出:25
对象数组
可以创建对象数组来存储多个对象。
csharp
using System;
namespace Week7Practice
{
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public void PrintInfo()
{
Console.WriteLine($"{Name} - {Age}岁");
}
}
class Program
{
static void Main(string[] args)
{
// 创建对象数组
Person[] people = new Person[3];
// 初始化每个对象
people[0] = new Person { Name = "张三", Age = 25 };
people[1] = new Person { Name = "李四", Age = 30 };
people[2] = new Person { Name = "王五", Age = 28 };
Console.WriteLine("=== 人员列表 ===");
foreach (Person person in people)
{
person.PrintInfo();
}
}
}
}
输出:
=== 人员列表 ===
张三 - 25岁
李四 - 30岁
王五 - 28岁
对象集合(List)
为什么需要对象集合?
对象数组的问题:
- 长度固定,创建后不能改变
- 添加或删除元素需要创建新数组
- 使用不方便
对象集合的优势:
- 长度动态,可以自由添加/删除元素
- 提供丰富的方法(Add、Remove、Find等)
- 使用简单方便
List 基础
List<T> 是泛型集合,T 表示元素的类型。
csharp
// 创建对象的集合
List<Person> people = new List<Person>();
// 添加对象
people.Add(new Person { Name = "张三", Age = 25 });
people.Add(new Person { Name = "李四", Age = 30 });
people.Add(new Person { Name = "王五", Age = 28 });
// 遍历集合
foreach (Person person in people)
{
person.PrintInfo();
}
List 的常用操作
csharp
using System;
using System.Collections.Generic;
namespace Week7Practice
{
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Occupation { get; set; }
public void PrintInfo()
{
Console.WriteLine($"姓名:{Name},年龄:{Age},职业:{Occupation}");
}
}
class Program
{
static void Main(string[] args)
{
// 创建 List<Person> 集合
List<Person> people = new List<Person>();
Console.WriteLine("===== 添加元素 =====\n");
// 添加元素
people.Add(new Person { Name = "张三", Age = 25, Occupation = "程序员" });
people.Add(new Person { Name = "李四", Age = 30, Occupation = "设计师" });
people.Add(new Person { Name = "王五", Age = 28, Occupation = "产品经理" });
Console.WriteLine($"当前人数:{people.Count}");
Console.WriteLine("\n===== 遍历集合 =====");
foreach (Person person in people)
{
person.PrintInfo();
}
Console.WriteLine("\n===== 访问指定元素 =====");
Console.WriteLine("第一个元素:");
people[0].PrintInfo();
Console.WriteLine("最后一个元素:");
people[people.Count - 1].PrintInfo();
Console.WriteLine("\n===== 插入元素 =====");
people.Insert(1, new Person { Name = "赵六", Age = 27, Occupation = "测试工程师" });
Console.WriteLine($"插入后人数:{people.Count}");
foreach (Person person in people)
{
person.PrintInfo();
}
Console.WriteLine("\n===== 删除元素 =====");
people.RemoveAt(2); // 删除索引为2的元素(王五)
Console.WriteLine($"删除后人数:{people.Count}");
foreach (Person person in people)
{
person.PrintInfo();
}
Console.WriteLine("\n===== 查找元素 =====");
Person foundPerson = people.Find(p => p.Name == "李四");
if (foundPerson != null)
{
Console.WriteLine("找到:");
foundPerson.PrintInfo();
}
Console.WriteLine("\n===== 清空集合 =====");
people.Clear();
Console.WriteLine($"清空后人数:{people.Count}");
}
}
}
输出:
===== 添加元素 =====
当前人数:3
===== 遍历集合 =====
姓名:张三,年龄:25,职业:程序员
姓名:李四,年龄:30,职业:设计师
姓名:王五,年龄:28,职业:产品经理
===== 访问指定元素 =====
第一个元素:
姓名:张三,年龄:25,职业:程序员
最后一个元素:
姓名:王五,年龄:28,职业:产品经理
===== 插入元素 =====
插入后人数:4
姓名:张三,年龄:25,职业:程序员
姓名:赵六,年龄:27,职业:测试工程师
姓名:李四,年龄:30,职业:设计师
姓名:王五,年龄:28,职业:产品经理
===== 删除元素 =====
删除后人数:3
姓名:张三,年龄:25,职业:程序员
姓名:赵六,年龄:27,职业:测试工程师
姓名:李四,年龄:30,职业:设计师
===== 查找元素 =====
找到:
姓名:李四,年龄:30,职业:设计师
===== 清空集合 =====
清空后人数:0
List 常用方法
| 方法 | 说明 | 示例 |
|---|---|---|
Add(item) |
在末尾添加元素 | people.Add(person) |
Insert(index, item) |
在指定位置插入元素 | people.Insert(0, person) |
Remove(item) |
删除指定元素 | people.Remove(person) |
RemoveAt(index) |
删除指定位置的元素 | people.RemoveAt(0) |
Clear() |
清空所有元素 | people.Clear() |
Count |
获取元素数量 | int count = people.Count |
Find(predicate) |
查找符合条件的元素 | people.Find(p => p.Age > 20) |
FindAll(predicate) |
查找所有符合条件的元素 | people.FindAll(p => p.Age > 20) |
Contains(item) |
判断是否包含某元素 | bool has = people.Contains(person) |
Sort() |
对元素排序 | people.Sort() |
LINQ 方法(Where、GroupBy、OrderBy、Select)
LINQ(Language Integrated Query)提供了一套强大的查询方法,让我们能够方便地对集合进行筛选、排序、分组和转换操作。
注意: 使用 LINQ 方法需要添加命名空间 using System.Linq;
Where - 筛选数据
Where 方法用于根据条件筛选元素,返回符合条件的所有元素。
csharp
using System.Linq;
List<Person> people = new List<Person>
{
new Person { Name = "张三", Age = 25 },
new Person { Name = "李四", Age = 30 },
new Person { Name = "王五", Age = 28 },
new Person { Name = "赵六", Age = 22 }
};
// 筛选年龄大于25的人
var adults = people.Where(p => p.Age > 25);
Console.WriteLine("年龄大于25的人:");
foreach (Person person in adults)
{
Console.WriteLine($" {person.Name} - {person.Age}岁");
}
// 筛选名字包含"三"的人
var specificNames = people.Where(p => p.Name.Contains("三"));
Console.WriteLine("\n名字包含'三'的人:");
foreach (Person person in specificNames)
{
Console.WriteLine($" {person.Name}");
}
输出:
年龄大于25的人:
李四 - 30岁
王五 - 28岁
名字包含'三'的人:
张三
OrderBy / OrderByDescending - 排序
OrderBy 按升序排序,OrderByDescending 按降序排序。
csharp
using System.Linq;
List<Person> people = new List<Person>
{
new Person { Name = "张三", Age = 30 },
new Person { Name = "李四", Age = 22 },
new Person { Name = "王五", Age = 28 },
new Person { Name = "赵六", Age = 25 }
};
// 按年龄升序排序
var sortedByAge = people.OrderBy(p => p.Age);
Console.WriteLine("按年龄升序:");
foreach (Person person in sortedByAge)
{
Console.WriteLine($" {person.Name} - {person.Age}岁");
}
// 按年龄降序排序
var sortedByAgeDesc = people.OrderByDescending(p => p.Age);
Console.WriteLine("\n按年龄降序:");
foreach (Person person in sortedByAgeDesc)
{
Console.WriteLine($" {person.Name} - {person.Age}岁");
// 按姓名排序
var sortedByName = people.OrderBy(p => p.Name);
Console.WriteLine("\n按姓名排序:");
foreach (Person person in sortedByName)
{
Console.WriteLine($" {person.Name}");
}
输出:
按年龄升序:
李四 - 22岁
赵六 - 25岁
王五 - 28岁
张三 - 30岁
按年龄降序:
张三 - 30岁
王五 - 28岁
赵六 - 25岁
李四 - 22岁
按姓名排序:
张三
李四
王五
赵六
Select - 转换数据
Select 方法用于将集合中的每个元素转换为新的形式。
csharp
using System.Linq;
List<Person> people = new List<Person>
{
new Person { Name = "张三", Age = 25 },
new Person { Name = "李四", Age = 30 },
new Person { Name = "王五", Age = 28 }
};
// 只提取姓名
var names = people.Select(p => p.Name);
Console.WriteLine("所有姓名:");
foreach (string name in names)
{
Console.WriteLine($" {name}");
}
// 创建新的对象格式(只包含姓名和年龄)
var simplified = people.Select(p => new { p.Name, p.Age });
Console.WriteLine("\n简化信息:");
foreach (var item in simplified)
{
Console.WriteLine($" {item.Name}:{item.Age}岁");
}
// 计算年龄加10岁后的值
var futureAges = people.Select(p => p.Age + 10);
Console.WriteLine("\n10年后的年龄:");
foreach (int age in futureAges)
{
Console.WriteLine($" {age}岁");
}
输出:
所有姓名:
张三
李四
王五
简化信息:
张三:25岁
李四:30岁
王五:28岁
10年后的年龄:
35岁
40岁
38岁
GroupBy - 分组
GroupBy 方法用于根据某个条件对元素进行分组。
csharp
using System.Linq;
class Student
{
public string Name { get; set; }
public string Grade { get; set; }
public double Score { get; set; }
}
List<Student> students = new List<Student>
{
new Student { Name = "张三", Grade = "高三", Score = 85 },
new Student { Name = "李四", Grade = "高三", Score = 92 },
new Student { Name = "王五", Grade = "高二", Score = 78 },
new Student { Name = "赵六", Grade = "高二", Score = 88 },
new Student { Name = "孙七", Grade = "高三", Score = 90 }
};
// 按年级分组
var groupedByGrade = students.GroupBy(s => s.Grade);
Console.WriteLine("按年级分组:");
foreach (var group in groupedByGrade)
{
Console.WriteLine($"\n年级:{group.Key}");
Console.WriteLine($" 人数:{group.Count()}");
Console.WriteLine(" 学生:");
foreach (Student student in group)
{
Console.WriteLine($" - {student.Name}({student.Score}分)");
}
}
输出:
按年级分组:
年级:高三
人数:3
学生:
- 张三(85分)
- 李四(92分)
- 孙七(90分)
年级:高二
人数:2
学生:
- 王五(78分)
- 赵六(88分)
组合使用 LINQ 方法
LINQ 方法可以链式调用,实现复杂的查询。
csharp
using System.Linq;
List<Person> people = new List<Person>
{
new Person { Name = "张三", Age = 25 },
new Person { Name = "李四", Age = 35 },
new Person { Name = "王五", Age = 28 },
new Person { Name = "赵六", Age = 40 },
new Person { Name = "孙七", Age = 30 }
};
// 链式调用:筛选年龄大于25的,按年龄升序排序,只取前3个
var result = people
.Where(p => p.Age > 25)
.OrderBy(p => p.Age)
.Take(3);
Console.WriteLine("年龄大于25的前3人(按年龄升序):");
foreach (Person person in result)
{
Console.WriteLine($" {person.Name} - {person.Age}岁");
}
输出:
年龄大于25的前3人(按年龄升序):
王五 - 28岁
孙七 - 30岁
李四 - 35岁
LINQ 方法总结
| 方法 | 作用 | 返回类型 | 示例 |
|---|---|---|---|
Where |
筛选符合条件的元素 | IEnumerable<T> |
people.Where(p => p.Age > 18) |
OrderBy |
升序排序 | IOrderedEnumerable<T> |
people.OrderBy(p => p.Age) |
OrderByDescending |
降序排序 | IOrderedEnumerable<T> |
people.OrderByDescending(p => p.Age) |
Select |
转换元素 | IEnumerable<TResult> |
people.Select(p => p.Name) |
GroupBy |
按条件分组 | IEnumerable<IGrouping<TKey, T>> |
students.GroupBy(s => s.Grade) |
Take |
取前n个元素 | IEnumerable<T> |
people.Take(5) |
Skip |
跳过前n个元素 | IEnumerable<T> |
people.Skip(10) |
First |
取第一个元素 | T |
people.First() |
Last |
取最后一个元素 | T |
people.Last() |
Count() |
统计元素数量 | int |
people.Count() |
Sum() |
求和 | numeric |
people.Sum(p => p.Age) |
Average() |
求平均值 | double |
people.Average(p => p.Age) |
Max() |
求最大值 | T |
people.Max(p => p.Age) |
Min() |
求最小值 | T |
people.Min(p => p.Age) |
LINQ 实践:统计学生成绩
csharp
using System;
using System.Linq;
namespace Week7Practice
{
class Student
{
public string Name { get; set; }
public string Grade { get; set; }
public double Score { get; set; }
public void PrintInfo()
{
Console.WriteLine($" {Name} - {Grade} - {Score:F1}分");
}
}
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>
{
new Student { Name = "小明", Grade = "高三", Score = 92.5 },
new Student { Name = "小红", Grade = "高三", Score = 58.0 },
new Student { Name = "小刚", Grade = "高二", Score = 75.5 },
new Student { Name = "小丽", Grade = "高二", Score = 88.0 },
new Student { Name = "小伟", Grade = "高三", Score = 45.0 },
new Student { Name = "小芳", Grade = "高二", Score = 95.0 }
};
Console.WriteLine("===== 学生成绩统计 =====\n");
// 筛选及格学生
var passedStudents = students.Where(s => s.Score >= 60);
Console.WriteLine("--- 及格学生 ---");
foreach (Student s in passedStudents)
{
s.PrintInfo();
}
// 按成绩降序排序,取前3名
var top3Students = students
.OrderByDescending(s => s.Score)
.Take(3);
Console.WriteLine("\n--- 成绩前3名 ---");
foreach (Student s in top3Students)
{
s.PrintInfo();
}
// 按年级分组
var groupedByGrade = students.GroupBy(s => s.Grade);
Console.WriteLine("\n--- 按年级统计 ---");
foreach (var group in groupedByGrade)
{
double avg = group.Average(s => s.Score);
Console.WriteLine($"年级:{group.Key}");
Console.WriteLine($" 人数:{group.Count()}");
Console.WriteLine($" 平均分:{avg:F2}");
}
// 计算最高分和最低分
double maxScore = students.Max(s => s.Score);
double minScore = students.Min(s => s.Score);
double avgScore = students.Average(s => s.Score);
Console.WriteLine($"\n--- 整体统计 ---");
Console.WriteLine($"最高分:{maxScore:F1}");
Console.WriteLine($"最低分:{minScore:F1}");
Console.WriteLine($"平均分:{avgScore:F2}");
// 只提取姓名列表
var names = students.Select(s => s.Name);
Console.WriteLine($"\n--- 学生名单 ---");
Console.WriteLine($"所有学生:{string.Join(", ", names)}");
}
}
}
输出:
===== 学生成绩统计 =====
--- 及格学生 ---
小明 - 高三 - 92.5分
小刚 - 高二 - 75.5分
小丽 - 高二 - 88.0分
小芳 - 高二 - 95.0分
--- 成绩前3名 ---
小芳 - 高二 - 95.0分
小明 - 高三 - 92.5分
小丽 - 高二 - 88.0分
--- 按年级统计 ---
年级:高三
人数:3
平均分:65.17
年级:高二
人数:3
平均分:86.17
--- 整体统计 ---
最高分:95.0
最低分:45.0
平均分:75.67
--- 学生名单 ---
所有学生:小明, 小红, 小刚, 小丽, 小伟, 小芳
实践:学生信息管理系统
csharp
using System;
using System.Collections.Generic;
namespace Week7Practice
{
class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Grade { get; set; }
public double Score { get; set; }
public void PrintInfo()
{
Console.WriteLine($"姓名:{Name},年龄:{Age},年级:{Grade},成绩:{Score:F1}");
}
public bool IsPass()
{
return Score >= 60;
}
}
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>();
Console.WriteLine("===== 学生信息管理系统 =====\n");
// 添加学生
Console.WriteLine("--- 添加学生 ---");
students.Add(new Student { Name = "小明", Age = 18, Grade = "高三", Score = 92.5 });
students.Add(new Student { Name = "小红", Age = 17, Grade = "高二", Score = 58.0 });
students.Add(new Student { Name = "小刚", Age = 18, Grade = "高三", Score = 75.5 });
students.Add(new Student { Name = "小丽", Age = 17, Grade = "高二", Score = 88.0 });
students.Add(new Student { Name = "小伟", Age = 18, Grade = "高三", Score = 45.0 });
Console.WriteLine($"已添加 {students.Count} 名学生\n");
// 显示所有学生
Console.WriteLine("--- 所有学生信息 ---");
foreach (Student student in students)
{
student.PrintInfo();
}
// 计算平均分
double average = 0;
foreach (Student student in students)
{
average += student.Score;
}
average /= students.Count;
Console.WriteLine($"\n班级平均分:{average:F2}");
// 找出及格的学生
Console.WriteLine("\n--- 及格学生 ---");
List<Student> passedStudents = students.FindAll(s => s.IsPass());
Console.WriteLine($"及格人数:{passedStudents.Count}");
foreach (Student student in passedStudents)
{
student.PrintInfo();
}
// 找出不及格的学生
Console.WriteLine("\n--- 不及格学生 ---");
List<Student> failedStudents = students.FindAll(s => !s.IsPass());
Console.WriteLine($"不及格人数:{failedStudents.Count}");
foreach (Student student in failedStudents)
{
student.PrintInfo();
}
// 删除不及格的学生
Console.WriteLine("\n--- 删除不及格学生 ---");
foreach (Student student in failedStudents)
{
students.Remove(student);
}
Console.WriteLine($"剩余学生数:{students.Count}");
// 最终学生名单
Console.WriteLine("\n--- 最终学生名单 ---");
foreach (Student student in students)
{
student.PrintInfo();
}
}
}
}
输出:
===== 学生信息管理系统 =====
--- 添加学生 ---
已添加 5 名学生
--- 所有学生信息 ---
姓名:小明,年龄:18,年级:高三,成绩:92.5
姓名:小红,年龄:17,年级:高二,成绩:58.0
姓名:小刚,年龄:18,年级:高三,成绩:75.5
姓名:小丽,年龄:17,年级:高二,成绩:88.0
姓名:小伟,年龄:18,年级:高三,成绩:45.0
班级平均分:71.80
--- 及格学生 ---
及格人数:3
姓名:小明,年龄:18,年级:高三,成绩:92.5
姓名:小刚,年龄:18,年级:高三,成绩:75.5
姓名:小丽,年龄:17,年级:高二,成绩:88.0
--- 不及格学生 ---
不及格人数:2
姓名:小红,年龄:17,年级:高二,成绩:58.0
姓名:小伟,年龄:18,年级:高三,成绩:45.0
--- 删除不及格学生 ---
剩余学生数:3
--- 最终学生名单 ---
姓名:小明,年龄:18,年级:高三,成绩:92.5
姓名:小刚,年龄:18,年级:高三,成绩:75.5
姓名:小丽,年龄:17,年级:高二,成绩:88.0
对象数组 vs List
| 特性 | 对象数组 | List |
|---|---|---|
| 长度 | 固定 | 动态 |
| 添加元素 | 需要创建新数组 | 直接 Add() |
| 删除元素 | 需要创建新数组 | RemoveAt() |
| 查询 | 支持索引访问 | 支持索引访问 + 查找方法 |
| 性能 | 访问快 | 添加删除快 |
| 适用场景 | 固定数量、高性能 | 动态数量、灵活操作 |
何时使用?
✅ 使用对象数组:
- 元素数量固定
- 追求极致性能
- 不需要频繁添加/删除
✅ 使用 List:
- 元素数量动态变化
- 需要频繁添加/删除
- 需要查找、筛选等功能
本章总结
- ✅ 理解了面向对象编程(OOP)的概念
- ✅ 掌握了类和对象的关系
- ✅ 学会了定义类和创建对象
- ✅ 理解了属性(字段)和方法
- ✅ 了解了访问修饰符
- ✅ 学会了使用对象数组
- ✅ 掌握了 List 集合的使用
- ✅ 理解了对象数组和对象集合的区别