我正在创建一个类库,并且在使用泛型方面遇到了一些麻烦。我有一个ITransaction
接口,其集合为ITransactionItem
。每个ITranscation
可以是CapitalCall
或Distribution
。 CapitalCall
是ITransaction
,但还有一些其他属性。 CapitalCallItem
是ITransactionItem
,其中包含一些其他属性。 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继承自。
答案 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)
是的,你记下的接口应该尽我所能。这种“递归”声明适用于泛型,但问题是你是否真的需要首先制作那些通用的?递归声明是一种不经常使用的东西,因此很难让其他人使用你的课程。
至于为自己使用界面,您仍然可以创建一个不太通用的界面并实现它。