在哪些场景下适合使用C#的new修饰符实现方法隐藏?
C#
new修饰符合理使用示例:Fluent构建器模式的类型适配 核心场景说明
在实现链式调用的Fluent接口(最常见的是各类构建器)时,我们通常希望子类的同名方法返回更具体的子类类型,让调用者可以直接调用子类独有的方法,不需要额外的强制类型转换。这种场景下使用new修饰符是完全合理的,且优势远大于override。
代码实现示例
基类通用构建器
public class DbCommandBuilder { protected int _timeout; protected string _sql; public DbCommandBuilder WithSql(string sql) { _sql = sql; return this; } public virtual DbCommandBuilder WithTimeout(int seconds) { _timeout = seconds; return this; } // 其他通用方法,比如Build生成最终的DbCommand public virtual DbCommand Build() => new DbCommand(_sql, _timeout); }
子类特化构建器
我们针对SqlServer做特化的构建器,新增独有的加密配置方法。如果用override实现WithTimeout,返回值只能是基类DbCommandBuilder,调用完WithTimeout后就无法直接调用子类独有的WithEncryption方法,必须强转,非常影响使用体验。
此时用new修饰符重新定义WithTimeout即可完美解决问题:
public class SqlServerCommandBuilder : DbCommandBuilder { private bool _enableEncryption; // 用new修饰符,返回子类类型,内部复用基类逻辑 public new SqlServerCommandBuilder WithTimeout(int seconds) { base.WithTimeout(seconds); return this; } // 子类独有的配置方法 public SqlServerCommandBuilder WithEncryption(bool enable) { _enableEncryption = enable; return this; } // 重写Build方法生成SqlServer特有的Command public override DbCommand Build() { var command = base.Build(); command.EnableEncryption = _enableEncryption; return command; } }
使用效果对比
使用new修饰符的调用代码
// 链式调用完全流畅,不需要任何强转 var sqlServerCommand = new SqlServerCommandBuilder() .WithSql("SELECT Id,Name FROM Users") .WithTimeout(30) // 此处返回SqlServerCommandBuilder类型 .WithEncryption(true) // 可直接调用子类独有方法 .Build();
如果用override的调用代码
var sqlServerCommand = new SqlServerCommandBuilder() .WithSql("SELECT Id,Name FROM Users") .WithTimeout(30) // 此处返回DbCommandBuilder类型 // 必须强制转换才能调用子类方法,既麻烦又容易抛出转换异常 ((SqlServerCommandBuilder)this).WithEncryption(true) .Build();
符合要求的验证
- 不是演示用的简单示例:该实现是生产环境中Fluent构建器的通用方案,EF Core、ASP.NET Core等官方类库的构建器逻辑中都有类似实现。
- 相比
override的优势明确:彻底解决了链式调用时的类型丢失问题,不需要额外强转,代码更简洁,出错概率更低。 - 不是“没法重写才用new”的被动选择:基类的
WithTimeout本身是可重写的virtual方法,但override受语法限制不能修改返回值类型,new是主动选择的更优实现方案。 - 无混淆风险:子类
new的WithTimeout逻辑完全复用基类实现,除返回值类型更具体外,行为和基类完全一致,不管用基类变量还是子类变量调用,最终执行效果没有差异,符合调用者预期。
内容的提问来源于stack exchange,提问作者User1291
相关产品推荐
相关产品推荐

