如何移除传感器类中用于标识属性的空接口ISensorIdentifier
适配双标识模式的工厂传感器类设计
你的这个思路完全贴合实际场景——历史系统遗留的混合标识问题确实需要这种抽象基类来统一处理。不过可以给代码做一些规范和功能上的优化,让它更健壮、更符合C#的编码习惯:
核心设计思路回顾
你用空接口ISensorIdentifier作为不同标识类型的统一契约,这种方式能很好地隔离不同标识的实现细节,让Sensor类无需关心具体的标识形式,这个方向是完全正确的。
优化后的代码实现
// 主传感器类,遵循C#帕斯卡命名规范 public class Sensor { public ISensorIdentifier Id { get; set; } } // 标识基接口,添加通用方法以增强实用性 public interface ISensorIdentifier { // 用于比较两个标识是否相等 bool Equals(ISensorIdentifier other); // 生成唯一键,方便日志、存储等场景使用 string GetUniqueKey(); } // 名称型传感器标识 public class NamedSensorId : ISensorIdentifier { // 只读属性确保标识不可修改 public string Name { get; } // 构造函数强制初始化Name,避免空值 public NamedSensorId(string name) { Name = name ?? throw new ArgumentNullException(nameof(name), "传感器名称不能为空"); } public bool Equals(ISensorIdentifier other) { return other is NamedSensorId otherNamed && otherNamed.Name == Name; } public string GetUniqueKey() { return $"named:{Name}"; } // 重写Object基类方法,确保集合操作时的相等性判断符合预期 public override bool Equals(object obj) { return Equals(obj as ISensorIdentifier); } public override int GetHashCode() { return Name.GetHashCode(); } } // 区域ID+传感器ID型标识 public class AreaAndSensorId : ISensorIdentifier { public int AreaId { get; } public int SensorId { get; } public AreaAndSensorId(int areaId, int sensorId) { AreaId = areaId; SensorId = sensorId; } public bool Equals(ISensorIdentifier other) { return other is AreaAndSensorId otherId && otherId.AreaId == AreaId && otherId.SensorId == SensorId; } public string GetUniqueKey() { return $"area:{AreaId}-sensor:{SensorId}"; } public override bool Equals(object obj) { return Equals(obj as ISensorIdentifier); } public override int GetHashCode() { return HashCode.Combine(AreaId, SensorId); } }
优化点说明
- 命名规范:把类名改成帕斯卡命名法(比如
sensor→Sensor),符合C#的通用编码标准,提升代码可读性。 - 强制初始化:给标识类添加构造函数,确保关键属性在实例化时就被赋值,避免空引用异常。
- 增强实用性:给
ISensorIdentifier添加Equals和GetUniqueKey方法,解决空接口无法直接比较、无法生成唯一标识的问题,后续在集合中存储传感器、打印日志等场景会更方便。 - 重写基类方法:重写
Object.Equals和GetHashCode,确保当把标识对象放到HashSet、Dictionary等集合中时,相等性判断符合预期。
内容的提问来源于stack exchange,提问作者Maxime
相关产品推荐
相关产品推荐

