具有约束层次结构的泛型

时间:2010-05-22 01:08:26

标签: c# generics oop circular-dependency

我目前面临一个非常令人不安的问题:

interface IStateSpace<Position, Value>
where Position : IPosition           // <-- Problem starts here
where Value : IValue                 // <-- and here as I don't
{                                    //     know how to get away this
                                     //     circular dependency!
                                     //     Notice how I should be
                                     //     defining generics parameters
                                     //     here but I can't!
    Value GetStateAt(Position position);
    void SetStateAt(Position position, State state);
}

当你在这里时,IPositionIValueIState都相互依赖。我怎么能逃脱这个?我想不出任何其他设计会绕过这种循环依赖,仍然准确描述我想要做的事情!

interface IState<StateSpace, Value>
where StateSpace : IStateSpace        //problem
where Value : IValue                  //problem
{
    StateSpace StateSpace { get; };
    Value Value { get; set; }
}

interface IPosition
{
}

interface IValue<State>
where State : IState {      //here we have the problem again
    State State { get; }
}

基本上我有一个状态空间IStateSpace,其中包含状态IState。他们在州空间的位置由IPosition给出。然后每个州都有一个(或多个)值IValue。我正在简化层次结构,因为它比描述的要复杂一些。使用泛型定义此层次结构的想法是允许相同概念的不同实现(IStateSpace将作为矩阵作为图形等实现。)

我能逃脱这个吗?你如何解决这类问题?在这些情况下使用哪种设计?

由于

2 个答案:

答案 0 :(得分:5)

答案 1 :(得分:3)

问题是什么并不完全清楚 - 是的,你的泛型类型中存在循环依赖关系,但是可行。

我在Protocol Buffers中有类似的“问题”:我有“消息”和“建设者”,他们成对出现。所以接口看起来像这样:

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

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

这当然很难看,但它确实有效。您希望能够表达您目前无法表达的内容?您可以看到我对此on my blog的一些看法。 (关于协议缓冲区的系列的第2和第3部分在这里是最相关的。)

(另外,如果您要在类型参数中添加T前缀,它会使您的代码更加传统。目前看起来StateValue只是类。 )