简体   繁体   English

遍历父/子结构

[英]Looping through a parent / Child structure

I'm working on a game where it will be possible to target each mob's limbs specifically, so you could aim for the head, the legs, ... 我正在开发一款游戏,可以专门针对每个暴民的四肢,因此您可以瞄准头部,腿部...

I have this constructor: 我有这个构造函数:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null)
{
    this.Legs = new List<Leg> { new Leg(), new Leg() };
    this.Torso = new Torso();
    this.Arms = new List<Arm> { new Arm(), new Arm() };
    this.Heads = new List<Head>
    {
        new Head
        {
            Ears = new List<Ear> { new Ear(), new Ear() },
            Eyes = new List<Eye> { new Eye(), new Eye() }
        }
    };
}

All of these limbs inherit from interface ILimb . 所有这些ILimb都从接口ILimb继承。

What is the best way to be able to loop through all limbs, including childs (when applicable)? 能够绕过包括儿童在内的所有肢体的最佳方法是什么(如果适用)?

I could add a protected List<ILimb> { get; set; } 我可以添加一个protected List<ILimb> { get; set; } protected List<ILimb> { get; set; } protected List<ILimb> { get; set; } and then add each, but that's redundant. protected List<ILimb> { get; set; } ,然后添加每个,但这是多余的。

Any ideas or suggestions for improvement? 有任何改进的想法或建议吗?

The best way would be to have this structure instead: 最好的方法是改用以下结构:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null)
{
    this.Limbs = new List<ILimb>();
    this.Limbs.Add(new Legs() { Limbs = new List<Limb>() { new Leg(), new Leg() });
    this.Limbs.Add(new Torso());
    this.Limbs.Add(new Arms() { Limbs = new List<Limb>() { new Arm(), new Arm() });
    this.Limbs.Add(new Heads() { Limbs = new List<Limb>() { new Head() { Limbs = new List<Limb>() .... , ... });
}

you can tidy the code up but basically it should have a collection of limbs, and limbs should have collections of limbs so that you can have Head > Ears > Ear or whatever hierarchy you wish. 您可以整理代码,但基本上它应该具有四肢的集合,并且四肢应该具有四肢的集合,以便您可以具有Head> Ears> Ear或您想要的任何层次结构。

Then in your ILimb interface, give it a Limbs property 然后在您的ILimb界面中为其设置Limbs属性

public interface ILimb
{
    List<ILimb> Limbs { get; set; }
    List<ILimb> GetAllLimbs { get; }
}

And create an abstract base class Limb with this method: 并使用此方法创建抽象基类Limb:

public virtual GetAllLimbs()
{
// pseudocode: something like this (basically recurse through the children)
return this.Limbs().foreach (c => c.GetAllLimbs()).union(this.Limbs());
}

Then it can crawl down the hierarchy easily and retrieve every limb. 然后,它可以轻松地向下爬取层次结构并检索每个分支。

So you could do 所以你可以做

myHumanoid.GetAllLimbs().Where(c => c is Arm).TakeDamage(5);

for example. 例如。

You have custom models for all of your objects except one... a custom collection of models. 您为所有对象都拥有定制模型,除了一个...定制的模型集合 List<T> is a good start, but it doesn't have the functionality you're looking for. List<T>是一个好的开始,但是它没有您要寻找的功能。 Functionality you're trying to put into Humanoid but doesn't really belong there. 尝试将功能添加到Humanoid但实际上并不属于其中。

Implement something like this: 实现这样的事情:

public class LimbList<T> : IList<T> where T : ILimb
{
    // implement IList<T> here
}

Here you would include business logic for the collection of limbs. 在这里,您将包括用于收集肢体的业务逻辑。 For example: 例如:

  • If there are already 2 Arm objects in the backing collection, throw an exception when calling .Add() with an Arm object. 如果支持集合中已经有2个Arm对象,则使用Arm对象调用.Add()时将引发异常。
  • If there is already 1 Torso object in the backing collection, throw an exception when calling .Add() with a Torso object. 如果已经有1个Torso的支持集合对象,调用时抛出一个异常.Add()Torso对象。
  • etc. 等等

A Humanoid would then have a LimbList<ILimb> property: Humanoid然后将具有LimbList<ILimb>属性:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null)
{
    this.Limbs.Add(new Leg());
    this.Limbs.Add(new Leg());
    this.Limbs.Add(new Torso());
    this.Limbs.Add(new Arm());
    this.Limbs.Add(new Arm());
    this.Limbs.Add(new Head
        {
            // as an added exercise, how would you extend this concept to the Head object?
        });
}

And you can loop over that list easily: 您可以轻松地遍历该列表:

foreach (var limb in this.Limbs)

Essentially the point here is that a collection of objects is itself an object, with custom logic like any other object. 从本质上讲,这里的重点是对象集合本身就是一个对象,具有与其他任何对象一样的自定义逻辑。 Put object logic in the objects, put collection logic in the collections. 将对象逻辑放入对象中,将集合逻辑放入集合中。 There's no rule that says you must only use the built-in collections in the framework. 没有规则说您只能使用框架中的内置集合。

Given a legs list and an arms list, you can do this: 给定legs列表和arms列表,您可以执行以下操作:

IEnumerable<ILimb> limbs = ((IEnumerable<ILimb>)arms).Concat(legs);

And then iterate it: 然后迭代它:

foreach (var limb in limbs) 
{
    // limb is an ILimb and you can access anything in that interface 
    // for each limb
}

Another alternative is you could add a method to Humanoid like this: 另一种选择是,您可以像这样向Humanoid添加方法:

public IEnumerable<ILimb> GetLimbs() 
{
    foreach (var a in Arms)
    {
        yield return a;
    }
    foreach (var l in Legs)
    {
        yield return l;
    }
}

Then you could do something like: 然后,您可以执行以下操作:

foreach(var limb in someHumanoid.GetLimbs()) 
{

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM