.net 相互依赖的泛型类?

ss2ws0br  于 2023-10-21  发布在  .NET
关注(0)|答案(3)|浏览(120)

在这篇文章的底部是一个解决方案的例子,尽管很明显这个例子是无效的,因为它使用了BaseNode和BaseEdge,但在继承时没有提供类型。
我尝试创建一个抽象图类,其中节点类和边类也必须是抽象的。每个类的单独实现将添加方法和属性,以及从基类实现抽象方法。
我有一个现有的解决方案,它只使用基本类型的一切,但我很快发现自己在一个混乱的造型。
只有图形类必须公开,尽管其他类可以公开,因此涉及嵌套在图形类中的节点和边类的解决方案是可以接受的。
有没有什么方法可以使所有属性都是正确的类型,而不会在系统中的任何地方进行昂贵的强制转换?更重要的是,实现类不必到处强制转换,但在这种情况下,性能肯定是一个问题(实际上是),所以我宁愿完全避免强制转换。

abstract class Graph<TNode, TEdge>
    where TNode : BaseNode<TEdge>
    where TEdge : BaseEdge<TNode>
{
    TNode root;
    List<TNode> nodes;
    List<TEdge> edges;

    public abstract float process();
}

abstract class BaseNode<TEdge>
    // THIS HERE IS THE PROBLEM
    where TEdge : BaseEdge
{
    List<TEdge> inputs;

    public List<TEdge> Inputs
    {
        get
        {
            return inputs;
        }
    }

    public abstract float process();
}

abstract class BaseEdge<TNode>
    // THIS HERE IS THE PROBLEM
    where TNode : BaseNode
{
    TNode from;
    TNode to;

    public TNode To
    {
        get
        {
            return to;
        }
    }

    public TNode From
    {
        get
        {
            return from;
        }
    }

    public abstract float process();
}

@Marceln想看看我现有的实现,所以在这里。没有泛型也一样。

abstract class Graph
{
    BaseNode root;
    List<BaseNode> nodes;
    List<BaseEdge> edges;

    public abstract float process();
}

abstract class BaseNode
{
    List<BaseEdge> inputs;

    public List<BaseEdge> Inputs
    {
        get
        {
            return inputs;
        }
    }

    public abstract float process();
}

abstract class BaseEdge
{
    BaseNode from;
    BaseNode to;

    public BaseNode To
    {
        get
        {
            return to;
        }
    }

    public BaseNode From
    {
        get
        {
            return from;
        }
    }

    public abstract float process();
}

Node的实现可能看起来像这样:

class ImplementedNode : BaseNode
{
    public override float process()
    {
        foreach (ImplementedEdge edge in this.Inputs)
        {
            // Something
        }
    }

    public bool getImplementationSpecificInfo()
    {
        return true;
    }
}
yjghlzjz

yjghlzjz1#

如果您愿意放松对BaseEdgeBaseNode的约束,那么您可以像下面的示例中那样做。
我已经介绍了接口INodeIEdge,所以无论谁使用它都不允许创建BaseEdgeBaseNode的任何类型的具体子类。

public interface INode
{

}

public interface IEdge
{

}

public abstract class Graph<TNode, TEdge>
    where TNode : BaseNode<TEdge>
    where TEdge : BaseEdge<TNode>
{
    public TNode Root { get; set; }
    public List<TNode> Nodes { get; set; }
    public List<TEdge> Edges { get; set; }
}

public abstract class BaseNode<TEdge> : INode where TEdge: IEdge
{
    List<TEdge> inputs;

    public List<TEdge> Inputs
    {
        get
        {
            return inputs;
        }
    }

    public abstract float process();
}

public abstract class BaseEdge<TNode> : IEdge where TNode: INode
{
    TNode from;
    TNode to;

    public TNode To
    {
        get
        {
            return to;
        }
    }

    public TNode From
    {
        get
        {
            return from;
        }
    }

    public abstract float process();
}

public class ConcreteNode : BaseNode<ConcreteEdge>
{
    public override float process()
    {
        return 0;
    }
}

public class ConcreteEdge : BaseEdge<ConcreteNode>
{
    public override float process()
    {
        return 0;
    }
}

public class ConcreteGraph : Graph<ConcreteNode, ConcreteEdge>
{

}
g6ll5ycj

g6ll5ycj2#

更新

另一个答案,它提供了某种类型安全性。

public interface IGraph<TNode, TEdge>
    where TNode : INode
    where TEdge : IEdge
{
    TNode Root { get; set }
    List<TNode> Nodes { get; set; }
    List<TEdge> Edges { get; set; }
}

public interface INode
{
    List<IEdge> Edges { get; set; }
}

public interface INode<TEdge> where TEdge : IEdge
{
    List<TEdge> Edges { get; set; }
}

public interface IEdge
{
    INode To { get; set; }
    INode From { get; set; }
}

public interface IEdge<TNode> where TNode : INode
{
    TNode To { get; set; }
    TNode From { get; set; }
}


public class MyGraph : IGraph<MyNode, MyEdge>
{
    public MyGraph(MyNode root)
    {
        Root = root;
    }

    public MyNode Root { get; set; }
    public List<MyNode> Nodes { get; set; }
    public List<MyEdge> Edges { get; set; }
}

public class MyNode : INode<MyEdge>, INode
{
    public List<MyEdge> Edges { get; set; }

    List<IEdge> INode.Edges
    {
        get { return this.Edges; }
        set { this.Edges = value; }
    }
}

public class MyEdge : IEdge<MyNode>, IEdge
{
    public MyNode To { get; set; }
    public MyNode From { get; set; }

    INode IEdge.To
    {
        get { return this.To; }
        set { this.To = value; }
    }

    INode IEdge.From
    {
        get { return this.From; }
        set { this.From = value; }
    }
}

这样就不会出现编译错误。

更新

这个答案不起作用。但是,我把它留在这里的评论,与它出现。
@NodeDear,我认为你最初的例子在Graph是通用的时候是正确的:

Graph<TNode, TEdge> where TNode : BaseNode<TEdge>, TEdge : BaseEdge<TNode>

在您为@marceln提供的示例中,Graph类不是泛型。因此,你必须做各种各样的铸造。但是对于generic版本:

public abstract Graph<TNode, TEdge>
    where TNode : BaseNode<TEdge>
    where TEdge : BaseEdge<TNode>
{
    public TNode Root { get; set; }
    public List<TNode> Nodes { get; set; }
    public List<TEdge> Edges { get; set; }
}

public abstract BaseNode<TEdge> where TEdge : BaseEdge<BaseNode<TEdge>>
{
    public List<TEdge> Edges { get; set; }
}

public abstract BaseEdge<TNode> where TNode : BaseNode<BaseEdge<TNode>>
{
    public TNode To { get; set; }
    public TNode From { get; set; }
}

public class MyNode : BaseNode<TEdge> where TEdge : BaseEdge<MyNode>
{
    ...
}

public class MyEdge : BaseEdge<TNode> where TNode : BaseNode<MyEdge>
{
    ...
}

public class MyGraph : Graph<MyNode, MyEdge>
{
    ...
}

public MyGraph<MyNode, MyEdge> g = new MyGraph<MyNode, MyEdge>();
List<MyEdge> edges = g.Nodes[0].Edges;
MyNode toNode = g.Edges[0].To;

这允许从Graph<TNode, TEdge>派生的任何类型都具有强类型的节点和边,这正是OP所寻找的。

jgovgodb

jgovgodb3#

我找到了解决办法

public interface IGraph<TNode, TEdge>
    where TNode : INode<TNode, TEdge>
    where TEdge : IEdge<TNode, TEdge>
{
    public IEnumerable<TNode> Nodes { get; }
    public IEnumerable<TEdge> Edges { get; }
}

public interface INode<TNode, TEdge>
    where TEdge : IEdge<TNode, TEdge> 
    where TNode : INode<TNode, TEdge>
{
    IEnumerable<TEdge> Edges { get; }
    IEnumerable<TNode> Neighbors { get; }
}

public interface IEdge<TNode, TEdge>
    where TEdge : IEdge<TNode, TEdge> 
    where TNode : INode<TNode, TEdge>
{
    TNode To { get; }
    TNode From { get; }
}

public class Graph : IGraph<Node, Edge>
{
    public IEnumerable<Node> Nodes { get; }
    public IEnumerable<Edge> Edges { get; }
}

public class Node : INode<Node, Edge>
{
    public IEnumerable<Edge> Edges { get; }
    public IEnumerable<Node> Neighbors { get; }
}

public class Edge : IEdge<Node, Edge>
{
    public Node To { get; }
    public Node From { get; }
}

相关问题