我有一个这样的课程:
class BuildingFloor
{
// The list of building rooms;
// Room is "heavy" object with many-many fields
List< Room > m_rooms;
// The list of all apertures on the floor
List< Aperture > m_apertures;
...
List< Room > Rooms
{
get { return m_rooms; }
}
List< Aperture > Doors
{
get{ return GetAperturesOfType( 2 ); }
}
public List< Aperture > Exits
{
get{ return GetAperturesOfType( 3 ); }
}
...
List< Aperture > GetAperturesOfType( int type )
{
var apertures = new List<ApertureWrapper>();
foreach ( var aper in m_apertures )
{
if ( ( aper.Type == type ) )
{
apertures.Add( aper );
}
}
return apertures;
}
}
我的问题是:
1)当客户端代码访问m_rooms
属性时,将复制Rooms
;
2)在List<>
属性调用上构建Doors
个对象的次数。
那么,我可以在此代码中更改哪些内容以使其更快?
我需要在代码中大量使用这些属性
foreach( var door in m_floor.Doors) { ... }
注意:Profiler说Exits
属性花费了大量时间。证明:
答案 0 :(得分:4)
当客户端代码访问Rooms属性
时,是否会复制m_rooms
是。但m_rooms
的值只是一个引用 - 它本身不是List<Room>
对象。您可能想阅读我关于reference types and value types的文章。
在Doors属性调用上构造
List<>
个对象的次数。
GetAperturesOfType
一次,构建一个新的List<ApertureWrapper>
。您的财产将更简单地实施为:
return m_apertures.Where(x => x.Type == 2).ToList();
(听起来你可能也需要一个ApertureType
枚举...)
另请注意,如果只是需要遍历大门,您可以使用:
return m_apertures.Where(x => x.Type == 2);
并且完全避免创建List<>
。在其他方面,这会有不同的语义,请注意......
Profiler说Doors的财产花了很多时间。
嗯,你需要看看你实际获得了多少个光圈,有多少个光门,以及你调用Doors
属性的频率。我们无法从你向我们展示的内容中真正分辨出什么是重要的。绩效工作通常是情境性的。
编辑:现在我们已经看到了调用代码,如果使用局部变量会更好:
var exits = m_building.CurrentFloor.Exits;
for (int i = 0; i < exits.Count; i++)
{
// Use exits[i] within here
// Set exitId to i + 1 if you find the exit.
// (Or ideally, change everything to be 0-based...)
}
否则,您将为循环的每次迭代创建一个新列表。