尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

C# 方法重载与重写详解

C# 方法重载与重写详解 引言在C#面向对象编程中方法的重载Overloading和重写Overriding是两个基础且容易混淆的概念。它们都涉及到多个方法拥有相同的名称但实现机制、应用场景和编译时/运行时行为截然不同。本文将系统梳理两者的定义、语法、区别以及常见使用误区帮助读者彻底理清这两个知识点。1. 方法重载Overloading1.1 定义方法重载是指在同一个类中允许多个方法使用相同的名称但参数列表不同参数个数、类型或顺序不同。重载与返回值类型无关仅靠返回值类型不同无法构成重载。1.2 重载的条件方法名称相同参数列表不同个数、类型、顺序至少有一项不同发生在同一个类或派生类中也能对基类方法进行重载但通常指同一作用域不能仅通过返回值类型或参数修饰符如ref、out来区分1.3 示例代码publicclassCalculator{// 两个整数相加publicintAdd(inta,intb){returnab;}// 三个整数相加参数个数不同publicintAdd(inta,intb,intc){returnabc;}// 两个浮点数相加参数类型不同publicdoubleAdd(doublea,doubleb){returnab;}// 参数顺序不同publicstringConcat(intnumber,stringtext){return${number}-{text};}publicstringConcat(stringtext,intnumber){return${text}-{number};}}调用时编译器会根据传入的实参类型和数量自动匹配最合适的方法这属于编译时多态静态多态。1.4 可选参数与重载的冲突当方法带有默认参数时要注意避免产生二义性调用publicvoidPrint(inta,intb0){...}publicvoidPrint(inta){...}// 会产生调用歧义无法通过编译建议在设计中要么使用重载要么使用可选参数不要混用导致混淆。2. 方法重写Overriding2.1 定义方法重写是指派生类重新实现基类中已经定义的虚方法virtual、抽象方法abstract或重写了其他基类的方法override从而在运行时根据对象的实际类型决定调用哪个方法。2.2 重写的条件基类中的方法必须标记为virtual、abstract或本身已经是override派生类中使用override关键字进行重写方法签名必须完全一致名称、参数列表、返回值类型重写方法不能改变访问修饰符的可访问性例如不能将protected改为public但可以把protected internal改为public需谨慎2.3 示例代码// 基类publicclassAnimal{publicvirtualvoidSpeak(){Console.WriteLine(动物发出声音);}}// 派生类publicclassDog:Animal{publicoverridevoidSpeak(){Console.WriteLine(汪汪);}}publicclassCat:Animal{publicoverridevoidSpeak(){Console.WriteLine(喵喵);}}使用多态调用Animala1newDog();Animala2newCat();a1.Speak();// 输出汪汪a2.Speak();// 输出喵喵这种根据运行时对象类型来调用相应方法的行为属于运行时多态动态多态。2.4 重写的链路如果派生类本身又作为基类其override方法依然可以被更深层的子类重写除非使用sealed override阻断重写链。publicclassHusky:Dog{publicoverridevoidSpeak()// 可以继续重写{Console.WriteLine(嗷呜);}}publicclassSealDog:Dog{publicsealedoverridevoidSpeak()// 密封禁止后续重写{Console.WriteLine(汪密封);}}3. 重载与重写的主要区别对比维度重载Overloading重写Overriding发生位置同一个类或派生类中有继承关系的派生类中关键字无额外关键字基类virtual/abstract派生类override方法签名名称相同参数列表不同名称、参数、返回类型完全一致绑定时机编译时静态多态运行时动态多态返回值类型可以不同但不能仅靠它区分必须与基类一致或协变如有主要目的提供多种调用方式方便调用者替换或扩展基类行为与继承的关系不依赖继承可在同一类内实现必须通过继承实现4. 常见误区与最佳实践4.1 误区一重载可以只修改返回值类型错误示例publicintGetValue(){...}publicstringGetValue(){...}// 编译错误仅返回值类型不同4.2 误区二重写可以改变方法签名如果派生类中写了一个同名但参数不同的方法那不是重写而是隐藏new或重载publicclassBase{publicvirtualvoidDoWork(intx){}}publicclassDerived:Base{// 这不是重写而是隐藏如果有new或者产生编译器警告publicvoidDoWork(stringx){}}若要明确隐藏基类成员应使用new关键字若想重写必须签名一致并使用override。4.3 何时使用重载同一个操作有不同类型或数量的输入时如多种构造函数、多种Add方法提高代码的可读性和易用性4.4 何时使用重写基类定义通用行为派生类需要给出具体实现模板方法模式、策略模式等设计模式的实现基础框架和库提供的扩展点4.5 虚方法性能虚方法的调用存在微小的性能开销vtable 查询但对于绝大多数应用场景可以忽略不计。过早优化而避免使用重写是不明智的。5. 总结重载是编译时确定的多态关注“同一个方法名不同的参数”用来提供更方便的调用接口。重写是运行时多态基于继承关系让子类可以替换父类的虚方法行为是实现面向对象扩展性的核心机制。掌握重载与重写的区别是编写清晰、可扩展的C#代码的基础。建议在实际编码中多留意方法的签名和继承链避免混用new与override从而减少难以调试的隐藏 bug。
返回列表