我有一个对象池,每当我在池中的对象上调用Free()时,我都需要调用委托方法OnFree()。
在外部创建Free()并在创建池时在对象上设置。 OnFree从一个对象到另一个对象不同,有时它甚至是空的。
池中的对象继承自Poolable类。
class Poolable
{
public Action Free();
public Action OnFree();
}
目前,我通过这样做在继承类中创建OnFree:
class Light
{
public Light()
{
// Create method to be called when Free() is called on this light.
OnFree = () =>
{
DoStuffHere();
};
}
}
但是,这将为每个灯创建一个单独的委托,这会浪费一堆内存,尤其是当池中有数万个对象时。呃,每次调用这个构造函数时都会创建一个新的委托,对吗?
允许对象创建自己的OnFree()委托的好方法是什么,这样每个对象类型只有一个委托,而不是每个实例有一个委托?
我当然可以想到一种方式,但我希望有人能够想到一种“好”的方式 - 这种方式可以让人轻松维护。
编辑:我可以在基类中创建OnFree()委托静态,以便它以某种方式对每个继承类型是静态的吗?
编辑:阐明如何使用Pool,以及为什么Free()
是委托,而不是虚拟方法。如果您能想到更好的方法,请告诉我。
public class Pool<T> where T : Poolable
{
private int _liveCount;
private T[] _pool;
[...]
public Pool(int capacity, Func<T> allocateFunction)
{
[...]
// Fill pool with initial items:
for (int i = 0; i < capacity; i++)
{
T item = _allocate();
item.Free = () => Free(item);
_pool[i] = item;
}
}
/// <summary>
/// Frees given object from this pool. Object is assumed to
/// be in this pool.
/// </summary>
public void Free(Poolable obj)
{
obj.OnFree();
_liveCount -= 1;
[...]
}
}
答案 0 :(得分:2)
实际上取决于DoStuffHere()
的定义位置。如果这是一个实例方法,则会在编译器生成的类型上隐式捕获this
;同样可以捕获任何其他内容(在您的示例中未显示)。
在大多数正常情况下,委托实例的额外开销很小。避免传递创建委托的一种解决方法是使用参数化委托(Action<SomeStateType>
,可能存储在static
字段中),并将状态作为单独的参数提供...但当然,你正在为国家创造一个对象!进行手动捕获的一个小优点是,您可能(它取决于确切的代码示例)将其从2个(或更多)分配(1个委托,1个或更多捕获类)减少到1个分配(您的手动捕获) ;代表被关押在静态字段上。)
另一种方式,可能会创建某些。就个人而言,直到你的分析显示它是一个瓶颈,我认为你应该放松一下 - 分配非常快,大多数时候对象将在GEN-0中收集,这非常有效。< / p>
答案 1 :(得分:2)
如何保持简单:
class Poolable
{
public virtual void Free() { }
public virtual void OnFree() { } // naming not according to BCL std
}
class Light : Poolable
{
public override void Free() { }
...
}
答案 2 :(得分:1)
如果您使用静态通用类,则每种类型都会获得一个“实例” - 这正是您所追求的。因此,使用这样的类作为特定于类型的委托的backstore,并且在每个Poolable子类的静态构造函数中初始化它们将解决您的问题。请参阅示例代码:
public class Poolable
{
public Action Free { get; set; }
public Action OnFree { get { return GetOnFree(); } }
protected virtual Action GetOnFree() { throw new NotImplementedException(); }
}
public static class PoolHelper<T> where T : Poolable
{
public static Action OnFree { get; set; }
}
public class Light : Poolable
{
static Light()
{
PoolHelper<Light>.OnFree = () =>
{
// Define 'OnFree' for the Light type here...
// and do so for all other other sub-classes of Poolable
};
}
protected override Action GetOnFree()
{
return PoolHelper<Light>.OnFree;
}
}