Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有约束层次结构的泛型_C#_Generics_Oop_Circular Dependency - Fatal编程技术网

C# 具有约束层次结构的泛型

C# 具有约束层次结构的泛型,c#,generics,oop,circular-dependency,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

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

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);
}
基本上我有一个状态空间
IStateSpace
,里面有状态
IState
。它们在状态空间中的位置由
i位置给出。然后,每个状态都有一个(或多个)值
IValue
。我正在简化层次结构,因为它比描述的要复杂一些。使用泛型定义此层次结构的想法是允许相同概念的不同实现(将
IStateSpace
实现为矩阵和图形等)

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


谢谢

我看不出您想要实现什么-为什么要使用泛型将具体类型强制到接口中?这似乎完全违背了接口的意图——不使用具体类型。以下非通用定义有什么问题

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; }
}
然后您可以创建具体的实现

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;
    }
}
现在您可以决定在需要
IStateSpace
实例的地方使用
MatrixStateSpace
GraphStateSpace
实例。当然,所有其他类型的情况也是如此


实现中最具挑战性的部分是您必须创建新实例的时候。例如,
IStateSpace
中可能定义了一个方法
IState AddNewState()
IStateSpace
的任何具体实现都面临创建
IState
实例的问题(理想情况下),而不知道实现
IState
的任何具体类型。这就是工厂、依赖注入和相关概念发挥作用的原因。

我看不出您想要实现什么-为什么要使用泛型将具体类型强制到接口中?这似乎完全违背了接口的意图——不使用具体类型。以下非通用定义有什么问题

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; }
}
然后您可以创建具体的实现

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;
    }
}
现在您可以决定在需要
IStateSpace
实例的地方使用
MatrixStateSpace
GraphStateSpace
实例。当然,所有其他类型的情况也是如此


实现中最具挑战性的部分是您必须创建新实例的时候。例如,
IStateSpace
中可能定义了一个方法
IState AddNewState()
IStateSpace
的任何具体实现都面临创建
IState
实例的问题(理想情况下),而不知道实现
IState
的任何具体类型。这是工厂、依赖注入和相关概念发挥作用的结果。

问题是什么还不完全清楚-是的,泛型类型中存在循环依赖,但这是可行的

我有一个类似的“问题”:我有“消息”和“构建器”,它们成对出现。因此,接口如下所示:

public interface IMessage<TMessage, TBuilder>
    where TMessage : IMessage<TMessage, TBuilder> 
    where TBuilder : IBuilder<TMessage, TBuilder>
公共接口IMessage
where-TMessage:IMessage
制造商:IBuilder

公共接口IBuilder:IBuilder
where-TMessage:IMessage
制造商:IBuilder
这确实很难看,但它很管用。你想表达什么是你目前无法表达的?你可以看到我对此的一些想法。(关于协议缓冲区的系列文章的第2部分和第3部分在这里最为相关。)


(顺便说一句,如果在类型参数中添加
T
前缀,会使代码更加常规。目前看来
State
Value
只是类。)

问题不完全清楚-是的,泛型类型中存在循环依赖,但这是可行的

我有一个类似的“问题”:我有“消息”和“构建器”,它们成对出现。因此,接口如下所示:

public interface IMessage<TMessage, TBuilder>
    where TMessage : IMessage<TMessage, TBuilder> 
    where TBuilder : IBuilder<TMessage, TBuilder>
公共接口IMessage
where-TMessage:IMessage
制造商:IBuilder

公共接口IBuilder:IBuilder
where-TMessage:IMessage
制造商:IBuilder
这确实很难看,但它很管用。你想表达什么是你目前无法表达的?你可以看到我对此的一些想法。(关于协议缓冲区的系列文章的第2部分和第3部分在这里最为相关。)

(另一方面,如果在类型参数中添加
T
前缀,则会使代码更为常规。目前看来
State
Value
只是类。)