代码之家  ›  专栏  ›  技术社区  ›  Jesse Hufstetler

使用基类列表创建基类

c#
  •  0
  • Jesse Hufstetler  · 技术社区  · 7 年前

    我有 Bill s和 Receipt Lines ,但是 Receipt.Lines 充满了 ReceiptLine s和 Bill.Lines 充满了 BillLine s、 我希望他们都继承一个名为 Document 有财产的 线 DocumentLine 这样我可以偶尔将它们传递给 文件 s、 但我不想 myReceipt.Lines.Select(line => (ReceiptLine)line) 每次我特别使用 收据 . 有没有一种优雅的方法可以做到这一点?

    请注意,以下尝试导致 CS1503 Argument 1: cannot convert from 'Receipt' to 'Document<DocumentLine>'

    void Main()
    {
        var something = new Receipt();
        DoStuff(something);
    }
    public void DoStuff(Document<DocumentLine> document) { }
    
    public abstract class DocumentLine { }
    public class BillLine : DocumentLine { }
    public class ReceiptLine : DocumentLine { }
    public abstract class Document<TDocLine> where TDocLine : DocumentLine
    {
        public List<TDocLine> Lines { get; set; }
    }
    public class Bill : Document<BillLine> { }
    public class Receipt : Document<ReceiptLine> { }
    
    0 回复  |  直到 7 年前
        1
  •  2
  •   Olivier Jacot-Descombes    7 年前

    请注意,重写时不能更改类型,但可以将行类型设置为泛型参数。

    public abstract class DocumentLine { ... }
    public class BillLine : DocumentLine { ... }
    public class ReceiptLine : DocumentLine { ... }
    
    public abstract class Document<TDocLine> where TDocLine : DocumentLine
    {
        public List<TDocLine> Lines { get; set; }
    }
    
    public class Bill : Document<BillLine> { ... }
    public class Receipt : Document<ReceiptLine> { ... }
    

    从公共基派生行类型具有优势。1) 您可以重用两种行类型共有的内容。2) 您可以限制 TDocLine . 这更安全,因为它不允许您指定不适当的类型,并且允许您访问在 DocumentLine 从其他方法 Document<TDocLine>

        2
  •  2
  •   Rhaokiel    6 年前

    可以使用泛型类型定义列表项类型,如下所示:

    interface DocumentLine { }
    class BillLine : DocumentLine { }
    class ReceiptLine : DocumentLine { }
    
    class Document<T> where T : DocumentLine
    {
        public List<T> Lines { get; set; }
    }
    
    class Bill : Document<BillLine> { }
    
    class Receipt : Document<ReceiptLine>   { }
    

    编辑: 新的隐含问题所指的是 Generic Covariance out keyword (generic modifier) ].

    相反,要获得所需的行为,必须将泛型变量作为带条件的泛型,而不是固定的协变类型。

    public void DoStuff<T>(Document<T> document) where T : DocumentLine { }