gpt4 book ai didi

c# - 我如何制作一个树数据结构,它可以为 parent 和 child 提供两种不同的泛型类型

转载 作者:太空宇宙 更新时间:2023-11-03 14:45:00 25 4
gpt4 key购买 nike

我很惭愧地承认我在这个问题上坐了很多很多小时。但我只想按照我在下面的图表中构建它的方式来实现它....

我想用大陆/国家/州和城市来模拟世界。每个模型都有一个对其父项的引用和一个对其子项的引用列表,除了世界只有子项(因为它不能有父项)并且城市只有一个父项引用因为它不会更深。 (我想实现它,例如“World”没有父字段,同样“city”没有 List<Children> 字段。

我打算在树状数据结构中实现它,如下所示(我省略了实现): Only interfaces shown for simplicity

为了让您了解接口(interface)代码,我在此处包含了它的最低限度:

public interface IRoot<TChild>
{
List<TChild> Children { get; set; }
void AddChild(TChild child);
}
public interface ILeaf<TParent>
{
TParent Parent { get; set; }
}
public interface INode<TParent, TChild> : IRoot<TChild>, ILeaf<TParent> { }

还有一些实现代码:

public class Root<TChild> : IRoot<TChild>
{
public List<TChild> Children { get; set; }
public void AddChild(TChild child) { //... }
}
public class Leaf<TParent> : ILeaf<TParent>
{
public TParent Parent { get; set; }
}
public class Node<TParent, TChild> : INode<TParent, TChild>
{
private IRoot<TChild> root;
private ILeaf<TParent> leaf;

//...
}

最后是我要构造的类的代码:

public class World : Root<Continent> { }
public class Continent : Node<World, Country> { }
public class Country : Node<Continent, State> { }
public class State : Node<Country, City> { }
public class City : Leaf<City> { }

问题来了:

现在在 Root<TChild>.AddChild(TChild) 中添加一个子对象我需要访问 <TChlid>.Parent所以我需要限制通用 TChildILeaf<IRoot<TChild>>像这样:

public class Root<TChild> : IRoot<TChild> where TChild : ILeaf<Root<TChild>>
{
public void AddChild(TChild child)
{
child.Parent = this;
}
}

但是这样做,我得到了错误

CS0311 C# The type cannot be used as type parameter in the generic type or method. There is no implicit reference conversion from to.

在这一行

public class World : Root<Continent> { }

最佳答案

最后,我找到了解决办法。它包括制作基类 Root<TChild>Node<TParent, TChild>抽象的。设置子项的父级被委托(delegate)给一个抽象方法。在具体实现中,泛型类型参数已经被解析,那么访问Parent就没有问题了。属性(property)。

我也稍微改变了界面。将 children 暴露为 List<TChild>是有问题的,因为它允许任何人绕过 AddChild 的添加逻辑通过直接添加到列表并忘记设置 child 的 parent 。

我还制作了 Parent属性在接口(interface)中是只读的,因为 setter 仅在实现中使用。

public interface IRoot<TChild>
{
IReadOnlyList<TChild> Children { get; }
void AddChild(TChild child);
}

public interface ILeaf<TParent>
{
TParent Parent { get; }
}

public interface INode<TParent, TChild> : IRoot<TChild>, ILeaf<TParent>
{
}

基类:

public abstract class Root<TChild> : IRoot<TChild>
{
private List<TChild> _children = new List<TChild>();
public IReadOnlyList<TChild> Children => _children;

public void AddChild(TChild child)
{
_children.Add(child);
SetChildsParent(child);
}

protected abstract void SetChildsParent(TChild child);
}

public class Leaf<TParent> : ILeaf<TParent>
{
public TParent Parent { get; internal set; }
}

public abstract class Node<TParent, TChild> : Root<TChild>, INode<TParent, TChild>
{
public TParent Parent { get; internal set; }
}

请注意 Node继承自 Root , 因此我们只需要补充一个 ILeaf实现。

具体实现类:

public class World : Root<Continent>
{
protected override void SetChildsParent(Continent child) => child.Parent = this;
}

public class Continent : Node<World, Country>
{
protected override void SetChildsParent(Country child) => child.Parent = this;
}

public class Country : Node<Continent, State>
{
protected override void SetChildsParent(State child) => child.Parent = this;
}

public class State : Node<Country, City>
{
protected override void SetChildsParent(City child) => child.Parent = this;
}

public class City : Leaf<State> { }

关于c# - 我如何制作一个树数据结构,它可以为 parent 和 child 提供两种不同的泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54811035/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com