具有约束层次结构的泛型

dev*_*ium 1 c# oop generics 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);
}
Run Code Online (Sandbox Code Playgroud)

正如你到这里,既IPosition,IValueIState互相依赖.我怎么能逃脱这个?我想不出任何其他设计会绕过这种循环依赖,仍然准确描述我想要做的事情!

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; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢

Dan*_*ner 5

我无法看到你想要实现的目标 - 为什么你想通过使用泛型强制将具体类型强加到你的接口中?这似乎完全违背了接口的意图 - 不使用具体类型.以下非泛型定义有什么问题?

public interface IStateSpace
{
    IState GetStateAt(IPosition position);
    void SetStateAt(IPosition position, IState state);
}

public interface IState
{
    IStateSpace StateSpace { get; }
    IValue Value { get; set; }
}

public interface IPosition
{
}

public interface IValue
{
    IState State { get; }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建具体的实现.

internal class MatrixStateSpace : IStateSpace
{
    IState GetStateAt(IPosition position)
    {
        return this.Matrix[position];
    }

    void SetStateAt(IPosition position, IState state)
    {
        this.Matrix[position] = state;
    }
}

internal class GraphStateSpace : IStateSpace
{
    IState GetStateAt(IPosition position)
    {
        return this.Graph.Find(position).State;
    }

    void SetStateAt(IPosition position, IState state)
    {
        this.Graph.Find(position).State = state;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以决定使用MatrixStateSpace或需要GraphStateSpace实例的IStateSpace实例.当然,对于所有其他类型也是如此.

实现的挑战在于您必须创建新实例.例如,可能有一个IState AddNewState()定义的方法IStateSpace.任何具体的实现都IStateSpace面临着在IState不知道任何具体类型实现的情况下创建实例(理想情况)的问题IState.这是工厂,依赖注入和相关概念发挥作用.