目录
一、静态成员(static)
1. 核心概念
2. 调用规则
完整代码示例
3. 静态成员共享特性测试
二、只读(readonly)与常量(const)
核心区别
完整代码
三、类的继承
1. 继承基础规则
2. 访问权限(继承相关)
完整代码
四、父子类构造函数执行顺序
核心规则
完整代码
五、五大访问修饰符
权限对照表
1. 本项目测试代码
2. 跨项目测试代码(引用上方命名空间)
六、多态:函数重载(静态多态)
1. 多态分类
2. 函数重载条件(必须全部满足)
代码示例
七、运算符重载
规则
完整代码(盒子对象运算)
八、抽象类(abstract)
核心特点
完整代码
总结
一、静态成员(static)
1. 核心概念
- 非静态成员:属于对象(实例),每个对象拥有独立的数据,必须
new实例后调用。 - 静态成员:属于类本身,全局共享一份数据,通过
类名.成员直接调用,所有实例共用。
2. 调用规则
- 非静态方法:可以访问静态 / 非静态成员
- 静态方法:只能访问静态成员,不能直接调用实例成员(需手动创建对象)
完整代码示例
using System; namespace _2静态成员 { internal class Program { static void Main(string[] args) { // 非静态成员:实例对象调用 People p1 = new People(); p1.F1(); p1.Id = 1; // 静态成员:类名直接调用 People.Age = 10; People.F2(); } } public class People { // 非静态字段 + 属性 private int id; public int Id { get { return id; } set { Console.WriteLine("给Id赋值"); id = value; // 禁止写 Id = value,会造成属性死递归 } } // 非静态方法 public void F1() { Console.WriteLine("非静态方法 F1"); } // 静态自动属性 public static int Age { get; set; } // 静态方法 public static void F2() { Console.WriteLine("静态方法 F2"); } } }3. 静态成员共享特性测试
静态属性全局共享,一个实例修改,所有实例读取到的值都会变化:
using System; namespace _3静态成员测试 { internal class Program { static void Main(string[] args) { People p1 = new People(); p1.AddNum(); People p2 = new People(); p2.AddNum(); // 静态Num全局共享,结果均为 2 Console.WriteLine(p1.GetNum()); Console.WriteLine(p2.GetNum()); } } public class People { public int Age { get; set; } public static int Num { get; set; } public void AddNum() { Num++; } public int GetNum() { return Num; } } }二、只读(readonly)与常量(const)
核心区别
- const 常量
- 编译时常量,隐式 static,必须定义时直接赋值
- 全局不能修改,通过
类名.常量名访问
- readonly 只读字段
- 运行时常量,分实例只读和静态只读
- 实例只读:只能在实例构造函数中赋值
- 静态只读:只能在静态构造函数中赋值
- 静态构造函数
- 无访问修饰符、无参数
- 全局仅执行一次,首次使用类 / 创建实例时触发
完整代码
using System; namespace _4只读和常量 { internal class Program { static void Main(string[] args) { People p1 = new People(); // p1.a = 30; 报错:只读字段不能在构造函数外修改 Console.WriteLine(People.b); Console.WriteLine(People.c); } } public class People { // 实例只读字段 public readonly int a = 10; // 静态只读字段 public static readonly int b = 20; // 常量(隐式static) public const int c = 30; // 实例构造函数:修改实例只读 a public People() { a = 20; Console.WriteLine(a); } // 静态构造函数:修改静态只读 b,仅执行一次 static People() { b = 40; Console.WriteLine(b); } } }三、类的继承
1. 继承基础规则
- 语法:
子类 : 父类 - C# 为单继承:一个类只能直接继承一个父类,支持链式继承
- 所有类默认隐式继承
object(顶级基类) - 作用:代码复用、拓展功能
2. 访问权限(继承相关)
private私有:仅当前类内部访问,子类无法继承protected受保护:当前类 + 子类可访问,外部实例无法访问public公共:全场景可访问
完整代码
using System; namespace _5继承 { internal class Program { static void Main(string[] args) { Student s1 = new Student(); s1.Name = "Test"; s1.Address = "地址"; s1.F1(); } } // 父类 public class People { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } // 私有成员:子类不可访问 private int Age = 1000; // 受保护成员:子类可访问,外部实例不可访问 protected int CC { get; set; } public void F1() { Console.WriteLine("父类方法 F1"); } } // 子类 Student 继承父类 People public class Student : People { public void F2() { // 继承父类 public / protected 成员 Console.WriteLine($"{Name} {Id} {CC}"); } } }四、父子类构造函数执行顺序
核心规则
- 创建子类对象时,优先执行父类构造函数,再执行子类构造
- 默认自动调用父类无参构造,可通过
base(参数)指定调用父类有参构造 - 简写总结:
- 子类构造不写
base→ 父类必须有无参构造 - 子类构造写
base(参数)→ 父类可省略无参构造
- 子类构造不写
完整代码
using System; namespace _6子类构造和父类构造执行顺序 { internal class Program { static void Main(string[] args) { // 先执行父类有参构造 → 再执行子类有参构造 Student s2 = new Student(10, "张三"); } } public class People { public string Name { get; set; } // 父类无参构造 public People() { Console.WriteLine("父类无参构造"); } // 父类有参构造 public People(string name) { Name = name; Console.WriteLine("父类有参构造"); } } public class Student : People { public int Age { get; set; } // base() 可省略,默认调用父类无参构造 public Student() : base() { Console.WriteLine("子类无参构造"); } // base(n) 主动调用父类有参构造 public Student(int age, string n) : base(n) { Age = age; Console.WriteLine("子类有参构造:" + Name); } } }五、五大访问修饰符
权限对照表
| 修饰符 | 本类 | 子类 | 本项目实例 | 跨项目子类 | 跨项目实例 |
|---|---|---|---|---|---|
| public | ✅ | ✅ | ✅ | ✅ | ✅ |
| private | ✅ | ❌ | ❌ | ❌ | ❌ |
| protected | ✅ | ✅ | ❌ | ✅ | ❌ |
| internal | ✅ | ✅ | ✅ | ❌ | ❌ |
| protected internal | ✅ | ✅ | ✅ | ✅ | ❌ |
1. 本项目测试代码
using System; namespace _7属性访问修饰符 { internal class Program { static void Main(string[] args) { People p = new People(); Console.WriteLine(p.a); Console.WriteLine(p.d); Console.WriteLine(p.e); } } public class People { public int a = 10; private int b = 20; protected int c = 30; protected internal int d = 30; internal int e = 30; public void F1() { // 本类中所有修饰符都可访问 Console.WriteLine(a); Console.WriteLine(b); Console.WriteLine(c); Console.WriteLine(d); Console.WriteLine(e); } } // 本项目子类 public class Man : People { public void F2() { Console.WriteLine(a); Console.WriteLine(c); Console.WriteLine(d); Console.WriteLine(e); } } }2. 跨项目测试代码(引用上方命名空间)
using System; using _7属性访问修饰符; namespace _8测试访问修饰符 { internal class Program { static void Main(string[] args) { People p = new People(); Console.WriteLine(p.a); // public 跨项目可访问 } } // 跨项目子类 public class Woman : People { public void F3() { Console.WriteLine(a); Console.WriteLine(c); Console.WriteLine(d); // Console.WriteLine(e); internal 跨项目不可访问 } } }六、多态:函数重载(静态多态)
1. 多态分类
- 静态多态(编译期):函数重载、运算符重载
- 动态多态(运行期):虚方法、抽象类、接口
2. 函数重载条件(必须全部满足)
- 方法名完全相同
- 参数个数 / 类型 / 顺序不同
- 仅返回值不同,不构成重载
代码示例
using System; namespace _9多态_函数重载 { internal class Program { static void Main(string[] args) { } public static void F1() { Console.WriteLine("无参方法"); } public static void F1(int a) { Console.WriteLine("int 参数"); } public static void F1(string a) { Console.WriteLine("string 参数"); } public static void F1(string a, int b) { Console.WriteLine("两个参数"); } public static int F1(bool b) { Console.WriteLine("bool 参数"); return 10; } } }七、运算符重载
规则
- 使用
public static operator 运算符语法 - 必须为静态方法,参数至少包含一个当前类类型
- 常用重载:
+、-、++、>、<等
完整代码(盒子对象运算)
using System; namespace _10运算符号重载 { internal class Program { static void Main(string[] args) { Box b1 = new Box(10, 20, 30); Box b2 = new Box(30, 40, 50); // 重载 + Box b3 = b1 + b2; Console.WriteLine($"{b3.Length} {b3.Width} {b3.Height}"); // 重载 - int b4 = b1 - b2; Console.WriteLine(b4); // 重载 ++ Box b5 = b1++; Console.WriteLine(b1.Length); Console.WriteLine(b5.Length); // 重载 > < Console.WriteLine(b1 > b2); Console.WriteLine(b1 < b2); } } public class Box { public int Length { get; set; } public int Width { get; set; } public int Height { get; set; } // 体积 public int Volume { get { return Length * Width * Height; } } public Box() { } public Box(int l, int w, int h) { Length = l; Width = w; Height = h; } // 重载 + public static Box operator +(Box b1, Box b2) { return new Box { Length = b1.Length + b2.Length, Width = b1.Width + b2.Width, Height = b1.Height + b2.Height }; } // 重载 - public static int operator -(Box b1, Box b2) { return b1.Volume - b2.Volume; } // 重载 ++ public static Box operator ++(Box b1) { return new Box { Length = b1.Length + 1, Width = b1.Width + 1, Height = b1.Height + 1 }; } // 重载 > public static bool operator >(Box b1, Box b2) { return b1.Volume > b2.Volume; } // 重载 < public static bool operator <(Box b1, Box b2) { return b1.Volume < b2.Volume; } } }八、抽象类(abstract)
核心特点
- 用
abstract修饰,不能实例化,专门用于被继承 - 可包含:普通属性、普通方法、抽象属性 / 抽象方法
- 抽象方法:无方法体
{},子类必须用override重写实现 - 子类如果也是抽象类,可选择性不实现抽象成员;非抽象子类必须实现所有抽象成员
完整代码
using System; namespace _11抽象类 { internal class Program { static void Main(string[] args) { // People p = new People(); 报错:抽象类无法实例化 } } // 抽象父类 abstract class People { // 普通属性 public int Age { get; set; } // 普通方法 public void F2() { Console.WriteLine("普通方法"); } // 抽象属性(无实现) public abstract string Name { get; set; } // 抽象方法(无方法体) public abstract void F1(); } // 非抽象子类:必须重写所有抽象成员 class Student : People { public override string Name { get; set; } = "学生"; public override void F1() { Console.WriteLine("子类实现抽象方法 F1"); } } }总结
- 静态成员:类共享,静态方法只能访问静态成员
- readonly / const:const 编译常量,readonly 运行只读,赋值位置有严格限制
- 继承:C# 单继承,构造函数永远先执行父类
- 访问修饰符:控制跨类、跨项目、子类的访问权限
- 静态多态:函数重载、运算符重载,依赖参数区分
- 抽象类:模板类,强制子类实现抽象方法,不可实例化