C#基础09-面向对象关键字

零、文章目录

C#基础09-面向对象关键字

1、new 关键字

(1)作为运算符(创建对象)
  • 作用:在托管堆上分配内存并调用构造函数,返回对象引用。
  • 语法:
csharp 复制代码
ClassName obj = new ClassName();  // 引用类型 
int num = new int();             // 值类型(等价于 int num = 0)
  • 场景:
    • 实例化类、结构体或数组(如 List<int> list = new List<int>();)。
    • 为值类型调用默认构造函数(初始化默认值,如 int 初始化为 0)。
(2)作为修饰符(隐藏继承成员)
  • 作用:显式隐藏基类中的同名成员(字段、方法、属性等),消除编译器警告。
  • 语法:
csharp 复制代码
public class BaseClass {
    public void Method() => Console.WriteLine("Base");
}
 
public class DerivedClass : BaseClass {
    new public void Method() => Console.WriteLine("Derived"); // 隐藏基类方法 
}
  • 关键点:
    • 隐藏后,通过派生类实例访问的是新成员;通过基类引用访问原成员。
    • override 区别:new 创建新成员(无多态),override 扩展基类成员(支持多态)。
csharp 复制代码
DerivedClass d = new DerivedClass();
d.Method();       // 输出 "Derived"
((BaseClass)d).Method(); // 输出 "Base"
(3)作为泛型约束(限制类型参数)
  • 作用:要求泛型类型参数必须有公共无参构造函数。
  • 语法:
csharp 复制代码
public class Factory<T> where T : new() {
    public T Create() => new T(); // 可安全实例化 T 
}
  • 场景:泛型工厂模式(如 Factory<Employee>.Create())。
(4)注意事项
  • 命名冲突解决:优先使用 new 修饰符而非忽略警告,明确设计意图。
  • 内存管理:new 运算符为引用类型分配堆内存,需注意垃圾回收机制。
  • 值类型优化:new int()int num = 0 等效,编译器自动优化。

2、this 关键字

(1)四大核心作用
  • 区分成员变量与局部变量:当方法参数与类字段同名时,使用 this 明确指定成员变量:
csharp 复制代码
public class Person {
    private string name;
    public void SetName(string name) {
        this.name = name; // this.name 指代成员变量,name 为参数
    }
}
  • 链式调用构造函数:在构造函数中使用 this 调用同类其他构造函数,减少代码重复:
csharp 复制代码
public class Student {
    public string Name;
    public int Age;
    public Student(string name) : this(name, 18) { } // 调用下方构造函数
    public Student(string name, int age) {
        Name = name;
        Age = age;
    }
}
  • 传递当前对象引用:将当前实例作为参数传递给其他方法或类:
csharp 复制代码
public class Logger {
    public void Log(object obj) { /* 记录对象状态 */ }
}
public class User {
    public void Save() {
        new Logger().Log(this); // 传递当前 User 实例 
    }
}
  • 支持扩展方法:为现有类型添加新方法时,this 修饰首参数以绑定目标类型,无需修改源码即可增强类型功能
csharp 复制代码
public static class StringExtensions {
    public static bool IsNumeric(this string str) { // this 绑定 string 类型
        return double.TryParse(str, out _);
    }
}
// 调用:"123".IsNumeric();
(2)关键限制与注意事项
场景 是否允许使用 this 说明
静态方法(static ❌ 禁止 静态方法无实例上下文,使用将导致编译错误
静态属性访问器 ❌ 禁止 同静态方法限制
结构体(struct ⚠️ 受限 this 在结构体中是只读变量(不可修改引用)
构造函数链式调用 ✅ 推荐 仅限构造函数首行使用(如 : this(...)
(3)最佳实践与性能建议
  • 避免冗余使用:成员访问若无命名冲突,可省略 this(如 name = "Alice" 替代 this.name = "Alice"),提升代码简洁性。
  • 慎用于高频调用场景:this 本身无性能开销,但过度链式构造函数可能增加初始化复杂度。
  • 索引器实现 :通过 this[...] 语法定义类索引器,使对象支持类似数组的访问方式,增强数据封装灵活性。
csharp 复制代码
public class Collection {
    private int[] data = new int[10];
    public int this[int index] {
        get => data[index];
        set => data[index] = value;
    }
}
// 调用:Collection col = new(); col[0] = 100;
(4)错误用法示例
plain 复制代码
public class Example {
    private int id;
    public static void Print() {
        Console.WriteLine(this.id); // 错误:静态方法中禁止使用 this 
    }
}
  • ❌ 编译错误:CS0120: 非静态字段、方法或属性"Example.id"要求对象引用

3、base关键字

(1)核心用途
  • 调用基类构造函数
    • 当基类没有无参构造函数时,必须在派生类构造函数中通过base(参数)显式调用基类构造函数
    • 若未显式调用,编译器会尝试调用基类无参构造;若无参构造不存在,则编译报错
csharp 复制代码
public class Animal {
    public Animal(string name) => Console.WriteLine($"Animal: {name}");
}
public class Dog : Animal {
    public Dog(string name) : base(name) {  // 显式调用基类构造函数
        Console.WriteLine("Dog created");
    }
}
  • 调用基类被重写的方法
    • 子类重写基类虚方法(override)后,可通过base.方法名()保留基类逻辑
    • 适用于扩展而非完全替换基类方法的场景
csharp 复制代码
public class Base {
    public virtual void Show() => Console.Write("Hello");
}
public class Derived : Base {
    public override void Show() {
        base.Show();  // 调用基类方法
        Console.Write(" World");  // 扩展新逻辑
    }
}
// 输出:"Hello World"
  • 访问基类被隐藏的成员
    • 当子类使用new关键字隐藏基类同名成员时,可通过base访问基类原始成员
csharp 复制代码
public class Parent { public int Value = 100; }
public class Child : Parent {
    new public int Value = 200;  // 隐藏基类成员
    public void PrintBase() => Console.WriteLine(base.Value);  // 输出100
}
(2)关键限制与注意事项
  • 适用场景限制:
    • 仅在实例构造函数、实例方法或属性访问器中有效,静态方法中不可使用。
    • 只能访问直接基类的成员,无法跨级访问更高层基类。
  • 构造函数调用规则:
    • 若基类存在无参构造函数,子类可省略: base()(编译器自动调用);
    • 若基类只有有参构造,子类必须显式调用base并传参。
  • this的区别:this指向当前类实例,base指向直接基类实例。两者可结合使用(如this.Name vs base.Name)。
(3)典型场景速查表
场景 代码示例 作用
初始化基类字段 public Child(int x) : base(x) { } 确保基类数据正确初始化
扩展基类方法逻辑 base.Method(); /*新增逻辑*/ 复用基类方法并增强功能
解决父子类成员名冲突 int val = base.Field; 访问被隐藏的基类成员
  • 注意:滥用base可能破坏封装性。优先通过重写设计扩展逻辑,而非频繁绕过继承层级。

4、static关键字

(1)核心作用
  • 全局共享性
    • 修饰的成员(变量/方法)不属于对象实例,而是属于类本身
    • 所有实例共享同一份内存空间,修改一处即全局生效
csharp 复制代码
class Counter {
    public static int Count = 0;  // 所有实例共享 
    public Counter() { Count++; }
}
// 测试 
var c1 = new Counter(); 
var c2 = new Counter();
Console.WriteLine(Counter.Count); // 输出 2
  • 直接访问性:无需实例化类,通过 类名.成员 直接访问

Math.Pow(2, 3); // 经典静态方法调用

(2)五大使用场景
  • 静态成员变量
    • 特点:
      • 类加载时初始化,生命周期 = 应用程序域生存期
      • 默认值:数值型为 0,引用类型为 null
    • 典型用途:
      • 全局配置项(如日志开关)
      • 跨实例共享数据(如计数器)
  • 静态方法
    • 规则:
      • 只能访问静态成员,不可调用实例方法/属性
      • 不能使用 thisbase 关键字
    • 典型用途:
      • 工具类方法(如 File.ReadAllText()
      • 工厂模式创建对象
csharp 复制代码
public static Logger CreateLogger() { 
    return new FileLogger(); 
}
  • 静态类
    • 强制约束:
      • 类本身必须标记 static,且仅包含静态成员
      • 不可被实例化或继承(本质是 sealed abstract 类)
    • 典型用途:
      • 工具类(如 System.Math
      • 扩展方法容器(需配合 this 参数)
  • 静态构造函数
    • 特性:
      • 在类首次被访问时自动执行,且仅执行一次
      • 无参数和访问修饰符
    • 典型用途:初始化静态成员或加载资源
csharp 复制代码
class ConfigLoader {
    public static string ApiKey;
    static ConfigLoader() {
        ApiKey = File.ReadAllText("key.txt"); // 初始化
    }
}
  • 静态局部变量 (C# 8.0+)
    • 作用域:方法内定义,但生命周期延长至应用程序结束
    • 典型用途:跨方法调用保持状态(替代全局变量)
csharp 复制代码
void TrackCall() {
    static int callCount = 0; 
    callCount++;
    Console.WriteLine($"Called: {callCount} times");
}
(3)关键注意事项
  • 线程安全问题:静态成员默认非线程安全,高并发时需加锁
csharp 复制代码
private static readonly object _lock = new object();
public static void UpdateResource() {
    lock(_lock) { 
        // 修改共享资源 
    }
}
  • 内存泄漏风险:静态引用对象不会被 GC 回收,需手动解除引用
csharp 复制代码
static List<byte[]> _cache = new List<byte[]>();
// 长期持有大对象 → 可能泄漏
  • 初始化顺序:静态成员初始化顺序不可控,避免循环依赖
  • 测试困难:静态成员难以 Mock,过度使用降低代码可测试性
(4)最佳实践建议
  • 适用场景
    • ✅ 无状态工具方法(如数学计算)
    • ✅ 全局配置项(如应用设置)
    • ✅ 共享只读资源(如本地化字典)
  • 规避场景
    • ❌ 频繁修改的共享状态(优先用依赖注入)
    • ❌ 替代单例模式(需控制初始化时机的场景)
  • 性能优化
    • 只读静态数据标记 readonlyconst
    • 延迟初始化用 Lazy<T> 减少启动开销
csharp 复制代码
private static readonly Lazy<Logger> _logger = 
    new Lazy<Logger>(() => new Logger());
public static Logger Instance => _logger.Value;
(5)内存模型

5、sealed关键字

(1)核心功能与使用场景
  • 密封类(Sealed Class)
    • 作用:禁止其他类继承(相当于 Java 的 final)。
    • 典型场景:
      • 工具类(如 System.String),防止继承破坏设计逻辑。
      • 安全性要求高的类(如加密模块),避免恶意重写核心方法。
    • 语法:
csharp 复制代码
sealed class MyClass { /* 类成员 */ }  
  • 密封方法(Sealed Method)
    • 作用:阻止子类重写父类的虚方法。
    • 强制要求:必须与override联用,不能修饰非虚方法。
    • 语法:
csharp 复制代码
class Base {  
    public virtual void Method() { }  
}  
class Derived : Base {  
    public sealed override void Method() { } // 禁止孙类重写  
}
(2)关键技术特性
  • 性能优化
    • 密封类无派生类,JIT 编译器可将虚方法调用转为非虚调用,提升执行效率。
    • 示例:高频调用的密封类方法(如数学计算库)可减少运行时开销。
  • 设计约束
    • ❌ 禁止与 abstract 联用:抽象类要求被继承,而密封类禁止继承。
    • ❌ 不可修饰静态方法或属性:静态成员默认不可重写,无需密封。
  • 替代方案
    • 若需子类重写父类方法但限制孙类重写,可在中间层方法添加 sealed
(3)最佳实践与注意事项
  • 使用原则:
    • 慎用密封类:过度使用会降低代码扩展性,仅用于明确无需继承的场景。
    • 文档化理由:在代码注释中说明密封原因(如安全或性能需求)。
  • 常见误区:
    • 误用作"优化手段":除非性能测试证明瓶颈在虚方法调用,否则优先考虑代码可维护性。
    • 混淆 newsealed
      • sealed:禁止重写(要求方法原本是虚方法)。
      • new:隐藏父类同名方法(非重写)。
(4)综合示例
csharp 复制代码
// 密封类示例  
sealed class EncryptionService {  
    public void Encrypt(string data) { /* 核心加密逻辑 */ }  
}  
 
// 密封方法示例  
class Vehicle {  
    public virtual void StartEngine() { }  
}  
class Car : Vehicle {  
    public sealed override void StartEngine() { // 固定启动流程 }  
}  
class SportsCar : Car {  
    // 编译错误:无法重写密封方法 StartEngine()  
}
  • 设计提示:在框架开发中,密封核心类(如 System.IO.File)可确保行为一致性。
相关推荐
ajassi20003 小时前
开源 C# 快速开发(十四)进程--内存映射
开发语言·开源·c#
User_芊芊君子4 小时前
【Java ArrayList】底层方法的自我实现
java·开发语言·数据结构
敲代码的嘎仔4 小时前
牛客算法基础noob56 BFS
java·开发语言·数据结构·程序人生·算法·宽度优先
Never_Satisfied4 小时前
在JavaScript / HTML中,`onclick`事件触发多个函数
开发语言·javascript·html
ajassi20005 小时前
开源 C# 快速开发(十五)进程--windows消息
windows·开源·c#
ajassi20005 小时前
开源 C# 快速开发(十三)进程--管道通讯
开发语言·开源·c#
茉莉玫瑰花茶5 小时前
Qt 界面优化 --- 绘图
开发语言·数据库·qt
掘根5 小时前
【Qt】容器类控件——QTabWidget
开发语言·qt
hqwest5 小时前
QT肝8天07--连接数据库
开发语言·数据库·c++·qt·sqlite·上位机·qt开发