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

将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 19:20:58