You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为特定IVehicle实现强制指定对应的ITrackInfo特定实现?

问题描述

现有如下接口定义:

public interface IVehicle 
{
    ITrackInfo TrackInfo { get; set; }
    void ShowInfo();
}

public interface ITrackInfo
{
   int Length { get; set; }
}

以及ITrackInfo的三个实现类:

public class RailInfo : ITrackInfo
{
   public int Length { get; set;}
   public int SleeperSpacing { get; set; }
}

public class CanalInfo : ITrackInfo 
{
   public int Length  { get; set; }
   public decimal AverageDepth { get; set; }
}

public class RoadInfo : ITrackInfo
{ 
   public int Length { get; set; }
   public Color Colour { get; set; }
}

希望为每个IVehicle的实现类绑定对应的ITrackInfo特定实现(比如Train对应RailInfo、Boat对应CanalInfo),但直接按如下写法会编译失败——因为IVehicle要求TrackInfo必须是ITrackInfo类型:

public class Train : IVehicle 
{
   public RailInfo TrackInfo { get; set; }
   public void ShowInfo() {
      Console.WriteLine("Railway is {0}km long", TrackInfo.Length.ToString());
      Console.WriteLine("Distance between sleepers is {0}cm", TrackInfo.SleeperSpacing);
   }
}

public class Boat : IVehicle 
{
   public CanalInfo TrackInfo { get; set; }
   public void ShowInfo() {
      Console.WriteLine("Canal is {0}km long", TrackInfo.Length.ToString());
      Console.WriteLine("The average depth is {0}m", TrackInfo.AverageDepth.ToString("F2"));
   }
}

public class Bus : IVehicle
{
   public RoadInfo TrackInfo { get; set; }
   public void ShowInfo() {
      Console.WriteLine("Road is {0}km long", TrackInfo.Length.ToString());
      Console.WriteLine("The road is coloured {0}", TrackInfo.Colour.ToString());
   }
}

不想用ShowInfo里做类型检查这种不够优雅的方案:

var info = TrackInfo as RailInfo;
if (info == null)
{ 
    throw new Exception("Incorrect track info");
}

需求是找到一种能为特定IVehicle实现强制绑定对应ITrackInfo特定实现的优雅方式。


优雅解决方案:泛型接口约束

通过将IVehicle修改为泛型接口,并对泛型参数添加类型约束,就能在编译阶段确保每个车辆类绑定对应的轨道信息类型,完全避免运行时类型检查。

步骤1:修改IVehicle为泛型接口

public interface IVehicle<TTrackInfo> where TTrackInfo : ITrackInfo
{
    TTrackInfo TrackInfo { get; set; }
    void ShowInfo();
}

这里通过where TTrackInfo : ITrackInfo约束泛型参数必须实现ITrackInfo接口,保证类型合法性。

步骤2:修改车辆实现类

每个车辆类实现对应的泛型接口版本,指定具体的TTrackInfo类型:

public class Train : IVehicle<RailInfo>
{
    public RailInfo TrackInfo { get; set; }
    
    public void ShowInfo()
    {
        Console.WriteLine("Railway is {0}km long", TrackInfo.Length.ToString());
        Console.WriteLine("Distance between sleepers is {0}cm", TrackInfo.SleeperSpacing);
    }
}

public class Boat : IVehicle<CanalInfo>
{
    public CanalInfo TrackInfo { get; set; }
    
    public void ShowInfo()
    {
        Console.WriteLine("Canal is {0}km long", TrackInfo.Length.ToString());
        Console.WriteLine("The average depth is {0}m", TrackInfo.AverageDepth.ToString("F2"));
    }
}

public class Bus : IVehicle<RoadInfo>
{
    public RoadInfo TrackInfo { get; set; }
    
    public void ShowInfo()
    {
        Console.WriteLine("Road is {0}km long", TrackInfo.Length.ToString());
        Console.WriteLine("The road is coloured {0}", TrackInfo.Colour.ToString());
    }
}

方案优势

  • 编译时类型安全:如果给Train赋值非RailInfo类型的轨道信息,编译阶段直接报错,提前规避错误
  • 代码简洁:无需类型转换和空值检查,直接使用特定类型的属性和方法
  • 扩展性强:新增车辆类型和对应的轨道信息类型时,只需实现对应泛型接口即可,符合开闭原则

内容的提问来源于stack exchange,提问作者komodosp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:25:08