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

时间:2019-02-17 17:06:46

标签: c# reference xna iteration

我试图遍历实现特定接口的列表成员,称为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()在实现ImplementsGraphics

的RegisteredActors中所有Actor的所有返回结果

实际行为: 返回一个列表,该列表对于实现ImplementsGraphics的Registered Actor中的每个Actor重复相同的返回值。

编辑:

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

1 个答案:

答案 0 :(得分:0)

由于未提供任何代码状态,因此我只会显示您要重用对单个Model实例的引用以绘制多个对象。然后,您将同一实例的多个引用添加到List

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

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

在接口实现中,最好允许每个ActorStaticActor对象通过Model方法直接传递自己的GetModels(),而不是使用其他类MyOtherClass

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


我倾向于基于“ StaticCollidables”,“ DrawableStaticCollidables”和“ DrawableMovingCollidables”之类的属性来拆分派生的类和后续的List……

此技术可能需要更多的前期编码(因此不算“优雅”),但是在内存开销方面(8字节+(4(32位)或8(64位)字节) Listsizeof(Object)上)和CPU开销(无强制转换或is)。


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


请评论上述哪种解决方案对您有效(如有)。如果我错过了任何事情,请告诉我,以便我纠正答案。