Sto cercando di creare un sistema di particelle flessibile per il mio gioco XNA, e ho queste interfacce:
public interface IParticle : IUpdateable
{
bool Alive { get; }
float Percent { get; }
}
public interface IParticleEffect<T>
where T : IParticle
{
void Apply(GameTime time, ref T particle);
}
public interface IParticleEmitter<T> : IUpdateable
where T : IParticle
{
}
public interface IParticleRenderer<T> : IDrawable
where T : IParticle
{
}
L'idea alla base di questo sistema è che il codice cliente deve solo derivare da IParticle
, quindi creare una sottoclasse compatibile da IParticleEmitter
e IParticleRenderer
, e tutto il resto funziona solo automagicamente dietro le quinte. (In realtà sto scrivendo tutto al momento, ma gli ultimi due avrebbero una classe base astratta disponibile.)
Ad ogni modo, alcuni sistemi particellari amano usare le strutture mutevoli per scopi di ottimizzazione, ed è perfettamente ragionevole. Il mio sistema fornisce solo lo scheletro, e se il cliente decide che "Ehi, le strutture sono la strada da percorrere!", Allora il mio sistema dovrebbe supportare qualsiasi cosa il codice client gli getti. Questo è il motivo per cui il mio metodo IParticleEffect.Apply()
prende una particella per ref - è più economico passare una struct per riferimento piuttosto che copiarlo.
Sfortunatamente, si interrompe quando sono coinvolte le raccolte, perché l'iteratore foreach non gioca bene con gli oggetti passati da ref o out . Eric Lippert spiega perché qui .
Quindi, ora ho una decisione sul design da fare:
- Ignora completamente le strutture e modifica il mio vincolo in
where T: class, IParticle
. Ciò potrebbe danneggiare le future ottimizzazioni, ma rende molto più semplice lavorare con le raccolte. - Cambia tutto ciò che usa
ICollection<T>
oIEnumerable<T>
inIList<T>
così posso eseguire il polling manualmente tramite un indicizzatore. Ciò lo rende potenzialmente più potente, ma al costo di utilizzare un'interfaccia più profonda (elenco) per memorizzare i miei oggetti. - Qualcos'altro
Spero che questa domanda non sia troppo "dipende", ma sono curioso di sapere quali strategie posso applicare qui per farlo funzionare nel modo che voglio.
EDIT : mi sono reso conto che potevo includere anche una variabile locale come:
foreach (var particle in SomeParticleCollection)
{
var p = particle;
SomeEffect.Apply(ref p);
}
Tuttavia, p
avrebbe comunque l'effetto netto di copiarlo, anche questo non è l'ideale.