【问题标题】:Generic interfaces with abstract implementations具有抽象实现的通用接口
【发布时间】:2014-08-25 01:32:27
【问题描述】:

我正在尝试在 .NET 中实现一些图形搜索算法,以便进行有趣的个人教育。对于我的实现,我选择从实现以下接口的 Node 类开始:

public interface INode<T>
{
    T Data { get; }

    IDictionary<INode<T>, int> Neighbors { get; set; }
}

该节点包含一些 T 类型的Data,以及一个与它共享一条边的节点字典以及它们的整数距离。然后我想我可以创建一个抽象的Node 类:

public abstract class Node<T> : INode<T>
{
    public T Data { get; private set; }

    public IDictionary<INode<T>, int> Neighbors { get; private set; }

    public Node(T data, IDictionary<Node<T>, int> neighbors)
    {
        this.Data = data;

        this.Neighbors = neighbors;
    }
}

但是,上述方法不起作用,因为neighborsNeighbors 不匹配。我希望Node 的构造函数中的任何参数都包含IDictionary 特定类型的Node 而不仅仅是实现INode 的东西。例如,我以后可能会创建一个名为 GraphNode 的具体类,并且我想确保在构造函数中只使用 GraphNode。

为了解决这个问题,我可以简单地将 IDictionary Neighbors 从 INode 中取出,并将其放入抽象 Node 类中。尽管使用 FakeItEasy 之类的框架,这可能会限制我稍后测试该类的能力,而且我不确定它可能会产生什么其他影响。

对于如何普遍解决此问题,我将不胜感激。如果没有最好的解决方案,那么各种解决方案的优缺点是什么?

【问题讨论】:

    标签: c# asp.net inheritance design-patterns graph


    【解决方案1】:

    根据给定的代码,您可以做两件事来编译它。

    首先,代码也无法编译,因为INode&lt;T&gt; 没有完全实现。您的接口为Neighbors 定义了一个set 方法,因此您的set 必须是公开的,否则您必须显式实现该属性。

    其次,假设你真的想限制你的构造函数将neighbors 作为一个字典,以Node&lt;T&gt; 类而不是接口为键,加载this.Neighbors 的最快方法是更改​​行到

    this.Neighbors = neighbors.ToDictionary(
        neighborDistance => (INode<T>)neighborDistance.Key,
        neighborDistance => neighborDistance.Value
    );
    

    必须这样做,因为泛型 IDictionary is not covariant

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 2012-07-17
      • 1970-01-01
      • 2016-07-14
      • 2019-05-27
      • 2012-01-20
      • 2019-06-05
      相关资源
      最近更新 更多