将DocumentPlus转为Document时,如何把List<LinePlus>转为List<Line>?
解决方案
问题根源
你用new关键字隐藏了基类的Lines字段,导致Document和DocumentPlus各自持有独立的Lines字段。当把DocumentPlus强制转换为Document后,访问的是基类自身的空List<Line>,而非派生类中填充的List<LinePlus>。
方案1:属性+协变接口重构(推荐)
List<T>是不变类型,无法直接实现多态,但可以利用协变的IEnumerable<T>接口。修改基类为属性,派生类重写该属性,返回自身的LinePlus列表(LinePlus继承Line,IEnumerable<LinePlus>可隐式转换为IEnumerable<Line>):
public class Document { // 基类返回协变接口类型 public virtual IEnumerable<Line> Lines => _lines; protected List<Line> _lines = new List<Line>(); } public class Line { public string? A; } public class DocumentPlus : Document { // 派生类维护强类型列表 private List<LinePlus> _plusLines = new List<LinePlus>(); // 重写基类属性,自动协变转换为IEnumerable<Line> public override IEnumerable<Line> Lines => _plusLines; // 提供强类型访问入口 public List<LinePlus> PlusLines => _plusLines; } public class LinePlus : Line { public string? B; }
使用示例:
var x = new DocumentPlus(); x.PlusLines.AddRange(new List<LinePlus>() { new LinePlus() { A = "123", B = "456" }, new LinePlus() { A = "789", B = "101" }, new LinePlus() { A = "112", B = "131" } }); var y = (Document)x; var z = y.Lines; // 此处拿到的就是x.PlusLines中的元素,类型为IEnumerable<Line>
方案2:同步基类字段(不推荐,易出同步问题)
如果必须保留字段写法,可以在派生类的Lines赋值时同步更新基类字段:
public class DocumentPlus : Document { private List<LinePlus> _lines; public new List<LinePlus> Lines { get => _lines; set { _lines = value; // 同步基类Lines字段 base.Lines.Clear(); base.Lines.AddRange(value); } } }
这种方式能实现需求,但后续对DocumentPlus.Lines做增删操作时,基类Lines不会自动同步,需要额外维护,容易引发错误。
方案3:泛型基类(类型安全最优解)
若允许重构基类为泛型,可从根源避免类型转换问题:
public class Document<TLine> where TLine : Line { public List<TLine> Lines = new List<TLine>(); } public class Line { public string? A; } public class DocumentPlus : Document<LinePlus> { } public class LinePlus : Line { public string? B; }
使用时,直接转换为基类视角的列表:
var x = new DocumentPlus(); x.Lines = new List<LinePlus>() { new LinePlus() { A = "123", B = "456" }, new LinePlus() { A = "789", B = "101" }, new LinePlus() { A = "112", B = "131" } }; // 转换为List<Line> var z = x.Lines.Cast<Line>().ToList();
内容的提问来源于stack exchange,提问作者Avallex
相关产品推荐
相关产品推荐

