首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用基类列表创建基类

使用基类列表创建基类
EN

Stack Overflow用户
提问于 2019-06-11 00:38:39
回答 2查看 62关注 0票数 1

我有Bills和Receipts。这两种类型都有一个名为Lines的属性,但是Receipt.Lines充满了ReceiptLines,而Bill.Lines充满了BillLines。我希望它们都继承自一个名为Document的类,该类具有一个充满<ReceiptLine>D9BillLine>s的属性Lines,这样我就可以偶尔将它们传递给在Documents上操作的函数,但我不希望每次专门使用BillReceipt时都必须使用myReceipt.Lines.Select(line => (ReceiptLine)line)。有没有一种优雅的方法来做到这一点呢?

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

代码语言:javascript
运行
复制
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> { }
EN

回答 2

Stack Overflow用户

发布于 2019-06-11 00:48:15

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

代码语言:javascript
运行
复制
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”。在C#中,泛型协方差仅限于接口和委托类型[参见out keyword (generic modifier)]。

相反,为了获得您想要的行为,您必须携带泛型变量作为带条件的泛型,而不是固定的协变类型。

代码语言:javascript
运行
复制
public void DoStuff<T>(Document<T> document) where T : DocumentLine { }
票数 2
EN

Stack Overflow用户

发布于 2019-06-11 00:49:36

请注意,在重写时不能更改类型,但可以使线型成为泛型参数。

代码语言:javascript
运行
复制
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的实际类型。这样更安全,因为它不允许您指定不适当的类型,并且允许您从Document<TDocLine>类中的其他方法访问在DocumentLine中声明的公共成员。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56530288

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档