迭代期间无法获得单独的引用

问题描述 投票:0回答:1

我试图迭代实现特定接口的列表的成员,称为ImplementsGraphics,然后调用方法GetModels并将返回结果添加到列表中。

但是,每当我尝试遍历我的对象并执行转换操作时,我似乎在迭代期间覆盖了相同的引用。我已经推断出我的问题与我在何时,何时以及如何实例化我的变量有关,但我无法完全破译预期的行为。

我尝试了以下代码的大量排列:

public List<Model> GetModels()
        {
            var models = new List<Model>();

            foreach (Actor actor in registeredActors.Where(n=>n is ImplementsGraphics))
            {
                var graphicActor = (ImplementsGraphics)actor;
                models.AddRange(graphicActor.GetModels());
            }
            return models;
        }

问题行是var graphicActor = (ImplementsGraphics)actor;,但我不知道如何编写它,以便声明graphicsActor不会覆盖存储在模型中的现有实例。

在我的前几轮故障排除之前,我有

public List<Model> GetModels()
        {
            var models = new List<Model>();

            foreach (Actor actor in registeredActors)
            {
                if((ImplementsGraphics)actor != null)
                    models.AddRange(((ImplementsGraphics)actor).GetModels());
            }
            return models;
        }

我希望工作,因为我认为actor在迭代过程中是安全的,但显然不是。

期望的行为:返回一个列表,这是GetModels()在RegisteredActors中实现ImplementsGraphics的所有返回结果

实际行为:返回一个列表,该列表与已注册的Actor中的每个Actor重复的返回值相同,后者实现ImplementsGraphics。

编辑:

在类StaticActor,它是Actor的孩子并实现ImplementsGraphics,其定义如下:

public List<Model> GetModels()
    {
        foreach (ModelMesh mesh in model.Meshes)
        {
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.World = this.Transform.WorldMatrix;
            }
        }
        return new List<Model> { Model };
    }

另外,我尝试了另外两种也失败的方法。一个for循环,它遍历所有的RegisteredActors,并检查它们是否实现了ImplementsGraphics,在RegisteredActors中通过它们的索引明确地调用它们

和一个LINQ查询,它去了var models = RegisteredActors.Where(n=>n is ImplementsGraphics).SelectMany(n=>((ImplementsGraphics)n).GetModels())

编辑2:

我的类的定义在很大程度上是无关紧要的,如果你想要一个我可以解决的行为的可重现的例子,这是一个更简单的例子。

class MyClass
{
    MyOtherClass foo = new MyOtherClass();
    int bar = 0;

    MyOtherClass GetOtherClass()
    {
        foo.bar = bar;
        return foo;
    }
}

class MyOtherClass
{
    int bar = 0;
}

List<MyClass> MyCollection = new List<MyClass> {new MyClass(bar = 1), new MyClass(bar = 2), new Myclass(bar = 3)};
List<MyOtherClass> MyOtherCollection = new List<MyOtherClass>();
foreach(MyClass member in MyCollection)
{
    MyOtherCollection.Add(member.GetOtherClass());
}

如果你要执行上面的代码,我希望MyOtherCollection的bar属性的值为:1,2,3

但是,实际结果是:在第一次迭代期间,值为1在第二次迭代期间,值为2,2在第三次迭代期间,值为3,3,3

c# reference xna iteration
1个回答
0
投票

我会出现,因为没有提供的代码声明,只是暗示您试图重用对单个Model实例的引用来绘制多个对象。然后,您将同一实例的多个引用添加到List

解决方案可能与从所有static变量和/或容器对象中删除Model修饰符一样简单。

通常,解决方案是在将对象添加到Deep Copy时创建对象的List,但是,在XNA * 1中不能直接执行此操作。 (不是你想要的)

允许每个ActorStaticActor对象通过接口实现中的Model方法直接传递自己的GetModels(),而不是使用额外的类MyOtherClass会更好。

* 1。 XNA没有公开Model类的公共构造函数。可以使用反射来做到这一点。在MonoGame,有一个公共Constructor可用。


我倾向于根据“StaticCollidables”,“DrawableStaticCollidables”和“DrawableMovingCollidables”等属性拆分我的派生类和后续的Lists ...

这种技术可能需要更多的前期编码(因此不像“优雅”),但是,它在内存开销方面更有效(8字节+(4(32位)或8(64位)字节,具体取决于sizeof(Object))每List)和CPU开销(没有铸造或is)。


如果您尝试重用相同的模型,但将其放在不同的位置,请使用DrawInstancedPrimitives方法,使用模型的每个VertexBuffer中包含的Meshs。


请评论上述哪些解决方案适合您(如果有的话)。如果我错过了什么请告诉我,所以我可以纠正答案。

© www.soinside.com 2019 - 2024. All rights reserved.