如何让一个IComparer调用另一个IComparer?
复用已有IComparer实现,遵循DRY原则
你已经铺垫好了很好的基础,现在只需要让MovieDurationComparer依赖你写好的DurationComparer,就能完全复用现有逻辑,彻底避免重复代码。这里有两种实用的实现方式,你可以根据场景选择:
方式一:构造注入(推荐,灵活低耦合)
这种方式通过构造函数传入IComparer<Movie>实例,不仅能复用DurationComparer,还能支持后续扩展(比如以后需要换一种Movie比较规则时,完全不需要修改MovieDurationComparer):
class MovieDurationComparer : IComparer<Screening> { // 持有Movie比较器的引用 private readonly IComparer<Movie> _movieComparer; // 构造函数:默认使用DurationComparer,也允许传入其他自定义的Movie比较器 public MovieDurationComparer(IComparer<Movie> movieComparer = null) { // 如果没有传入比较器,就创建默认的DurationComparer实例 _movieComparer = movieComparer ?? new DurationComparer(); } public int Compare(Screening x, Screening y) { // 直接复用已有比较器的逻辑,不需要重复编写时长比较代码 return _movieComparer.Compare(x.Movie, y.Movie); } }
使用起来也很直观:
var screenings = new List<Screening> { s1, s2, s3, s4 }; // 使用默认的DurationComparer逻辑排序 screenings.Sort(new MovieDurationComparer()); // 如果以后需要换一种Movie比较规则(比如时长升序),只需要传入对应的比较器即可 screenings.Sort(new MovieDurationComparer(new AscendingDurationComparer()));
方式二:静态实例(简单直接,适合无状态比较器)
如果你的DurationComparer是无状态的(就像当前的实现),也可以直接在MovieDurationComparer里使用一个静态的DurationComparer实例,代码会更简洁:
class MovieDurationComparer : IComparer<Screening> { // 静态持有DurationComparer实例,避免重复创建对象 private static readonly IComparer<Movie> _durationComparer = new DurationComparer(); public int Compare(Screening x, Screening y) { // 复用已有时长比较逻辑 return _durationComparer.Compare(x.Movie, y.Movie); } }
这种方式代码量更少,但灵活性稍弱——如果以后需要修改Movie的比较规则,你得改动MovieDurationComparer里的静态实例。
这种实现的核心优势
- 严格遵循DRY原则:所有关于Movie时长比较的逻辑都集中在
DurationComparer里,不会在多个地方重复写y.DurationInMinutes.CompareTo(x.DurationInMinutes)这类代码 - 可维护性拉满:以后如果要修改Movie时长的比较规则(比如改成升序、加入额外判断),只需要修改
DurationComparer,所有依赖它的比较器都会自动生效 - 扩展性更强:构造注入的方式允许你随时替换Movie的比较逻辑,完全不需要改动
MovieDurationComparer的代码
内容的提问来源于stack exchange,提问作者Camelopardalus
相关产品推荐
相关产品推荐

