访问 class 的重对象成员的正确方法
The proper way of accessing heavy object members of class
我有一个 class 这样的:
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) 当客户端代码访问Rooms
属性;
时,是否会复制m_rooms
2) 在 Doors
属性 调用中将构造多少次 List<>
对象。
那么,我可以更改此代码以使其更快吗?
我需要在
这样的代码中大量使用这些属性
foreach( var door in m_floor.Doors) { ... }
注意:Profiler 说 Exits
属性 花费了大量时间。证明:
Will m_rooms be copied when client code will access Rooms property
是的。但是 m_rooms
的值只是一个引用——它本身并不是一个 List<Room>
对象。您可能想阅读我关于 reference types and value types.
的文章
How many times List<>
object will be constructed on the Doors property call.
- 调用了一次
GetAperturesOfType
,构造了一个新的List<ApertureWrapper>
。
您的 属性 可以更简单地实现为:
return m_apertures.Where(x => x.Type == 2).ToList();
(听起来您可能也想要一个 ApertureType
枚举...)
另请注意,如果您只是需要遍历门,您可以只使用:
return m_apertures.Where(x => x.Type == 2);
并完全避免创建 List<>
。请注意,这在其他方面会有不同的语义...
Profiler says Doors property spent significant amount of time.
好吧,您需要查看实际有多少个孔,有多少个门,以及您调用 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...)
}
否则,您将为循环的每次迭代创建一个新列表。
我有一个 class 这样的:
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) 当客户端代码访问Rooms
属性;
时,是否会复制m_rooms
2) 在 Doors
属性 调用中将构造多少次 List<>
对象。
那么,我可以更改此代码以使其更快吗?
我需要在
这样的代码中大量使用这些属性
foreach( var door in m_floor.Doors) { ... }
注意:Profiler 说 Exits
属性 花费了大量时间。证明:
Will m_rooms be copied when client code will access Rooms property
是的。但是 m_rooms
的值只是一个引用——它本身并不是一个 List<Room>
对象。您可能想阅读我关于 reference types and value types.
How many times
List<>
object will be constructed on the Doors property call.
- 调用了一次
GetAperturesOfType
,构造了一个新的List<ApertureWrapper>
。
您的 属性 可以更简单地实现为:
return m_apertures.Where(x => x.Type == 2).ToList();
(听起来您可能也想要一个 ApertureType
枚举...)
另请注意,如果您只是需要遍历门,您可以只使用:
return m_apertures.Where(x => x.Type == 2);
并完全避免创建 List<>
。请注意,这在其他方面会有不同的语义...
Profiler says Doors property spent significant amount of time.
好吧,您需要查看实际有多少个孔,有多少个门,以及您调用 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...)
}
否则,您将为循环的每次迭代创建一个新列表。