我试图遍历实现特定接口的列表成员,称为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
实际行为: 返回一个列表,该列表对于实现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
答案 0 :(得分:0)
由于未提供任何代码状态,因此我只会显示您要重用对单个Model
实例的引用以绘制多个对象。然后,您将同一实例的多个引用添加到List
。
解决方案可能就像从所有static
变量和/或容器对象中删除Model
修饰符一样简单。
通常,解决方案是在将对象添加到List
时创建对象的Deep Copy,但是,不可能直接在XNA
* 1中执行此操作。 (不是您想要的)
在接口实现中,最好允许每个Actor
或StaticActor
对象通过Model
方法直接传递自己的GetModels()
,而不是使用其他类MyOtherClass
。
* 1。 XNA
没有公开Model类的公共构造函数。使用反射来做到这一点是可能的。在MonoGame
中,有一个公共Constructor。
我倾向于基于“ StaticCollidables”,“ DrawableStaticCollidables”和“ DrawableMovingCollidables”之类的属性来拆分派生的类和后续的List
……
此技术可能需要更多的前期编码(因此不算“优雅”),但是在内存开销方面(8字节+(4(32位)或8(64位)字节) List的sizeof(Object)
上)和CPU开销(无强制转换或is
)。
如果您试图重用相同的模型,但是将其放置在不同的位置,请使用DrawInstancedPrimitives方法,并使用每个模型VertexBuffer
中包含的Mesh
。
请评论上述哪种解决方案对您有效(如有)。如果我错过了任何事情,请告诉我,以便我纠正答案。