C#通用类问题

时间:2010-06-21 19:21:33

标签: c# generics

我正在创建一个类库,并且在使用泛型方面遇到了一些麻烦。我有一个ITransaction接口,其集合为ITransactionItem。每个ITranscation可以是CapitalCallDistributionCapitalCallITransaction,但还有一些其他属性。 CapitalCallItemITransactionItem,其中包含一些其他属性。 CapitalCall的集合为CapitalCallItems。同样,存在Distribution类,其集合为DistributionItem

我尝试将Transaction接口设为通用:

interface ITransactionBase<TItem> 
    where TItem: ITransactionItem
{
    List<TItem> ITransactionItems
    {
        get;
        set;
    }

}

当我实现它时,这非常有效:

class CapitalCall : ITransactionBase<CapitalCallItem>

现在集合中的所有项目都是CapitalCallItem类型。

我遇到了以下问题。我想知道ITransaction上的同事ITranscationItem。我在类型为ITransactionItem的{​​{1}}表上创建了一个属性。当我使用此属性时,它不再输入正确的类:

ITranscation

我试过让var capitalCall = new CapitalCall(); var trans = capitalCall.TransactionItems[0].Transaction; // trans is now of the base type ITransaction, instead of typed to CapitalCall. 接口也使用泛型,但是当我尝试声明它时,我会陷入递归的通用噩梦。对此进行建模的正确方法是什么?

这会有效吗?

ITransactionLineItem

我很困惑如何自己如何使用界面 - 如果我想要一个混合interface ITransaction<TAction, TItems> where TItems : ITransactionItem<TAction, TItems> where TAction : ITransaction<TAction, TItems> interface ITransactionItem<TAction, TItems> where TItems : ITransactionItem<TAction, TItems> where TAction : ITransaction<TAction, TItems> 的集合,而不指定类型怎么办?另外我应该补充一点,我有实现接口的基本Transaction / Transaction项类,而CapitalCall / Dist继承自。

2 个答案:

答案 0 :(得分:2)

是的,这种相互递归的通用声明会起作用,但它会使非常复杂 - 我从经验中知道。如果您想要类似的示例,请查看我的协议缓冲区端口this declaration

public interface IMessage<TMessage, TBuilder> : IMessage<TMessage>
     where TMessage : IMessage<TMessage, TBuilder> 
     where TBuilder : IBuilder<TMessage, TBuilder>

IBuilder<,>具有相同的效果。

此声明还演示了您上一个问题的答案:如果您的界面的某些部分需要知道确切的交易类型,您可以在“不太通用”的基础上声明它们接口。所以你可以:

interface ITransaction<TAction, TItems> : ITransaction
    where TItems : ITransactionItem<TAction, TItems>
    where TAction : ITransaction<TAction, TItems>

例如,ITransaction是非通用接口。

但是,这不适合胆小的人。在我的情况下,我可以逃避它,因为几乎没有人使用原始接口 - 所有实现都是自动生成的,客户端代码使用那些非通用实现。在对开发人员进行实际使用之前,我会想很久很难......

答案 1 :(得分:1)

是的,你记下的接口应该尽我所能。这种“递归”声明适用于泛型,但问题是你是否真的需要首先制作那些通用的?递归声明是一种不经常使用的东西,因此很难让其他人使用你的课程。

至于为自己使用界面,您仍然可以创建一个不太通用的界面并实现它。