Hallo Leute,
Ich habe hier ne kleine Zwickmühle die mich stört weil die Lösung einfach unsauber ist.
Zuerst lege ich euch beide Interfaces vor und im Anschluss der Aufruf des Objektes.
Das Objekt wurde vom Interfacen "IComponent" == mit dem ersten Interface definiert -
brauchen tue ich aber in einem Fall die Methode des zweiten Interfaces (Drawable). Meine einzige Lösung war ein cast auf den zweiten Interface-Typ.
Den Code der Klasse welche beide Interfaces implementiert lasse ich weg. Es geht ja nur um die Möglichkeit die Methode des Drawable Interfaces zu erreichen und die Logik dieser Methode.
Hier der Kot:
interface IComponent
{
void Update(Single elapsedTime);
void Receive(Sender sender, Message message);
void SetManager(ComponentManager manager);
}
}
public interface Drawable
{
void Draw(RenderTarget target, RenderStates states);
}
class PlayerGraphicComponent : IComponent, Drawable
{
// Innenleben
}
class ComponentManager
{
private const Int16 _MAX_AMOUNT_OF_COMPONENTS_PER_GAMEOBJECT = 5;
private Int16 _currentSizeOfArray;
private IComponent[] _components;
public ComponentManager()
{
_components = new IComponent[_MAX_AMOUNT_OF_COMPONENTS_PER_GAMEOBJECT];
}
// Andere Methoden...
/// <summary>
/// Delivers the Draw-Method to a graphicComponent if available.
/// </summary>
/// <param name="target"></param>
/// <param name="states"></param>
public void Draw(RenderTarget target, RenderStates states)
{
Drawable graphicComponent;
for(int i = 0; i < _currentSizeOfArray; i++)
{
if (_components[i] is Drawable)
{
graphicComponent = (Drawable)_components[i];
graphicComponent.Draw(target, states);
}
}
}
Eine andere Möglichkeit wäre es halt in der Add(IComponent component) Methode (hier nicht einsehbar da ausgeblendet) das Object auf "is Drawable" zu prüfen und daraufhin direkt zu auf (Drawable) zu casten. Ist aber genau so hässlich und ich glaube das Downcasten ist eh verpönt.
Welche Herangehensweise könntet ihr vorschlagen? Ich habe zu wenig Erfahrung um mir noch mehr einfallen zu lassen 😉
gruß Charlie
Hi,
wenn dich das casten stört, dann nutz eben ein zusätzliches Interface.
public interface IDrawableComponent : IComponent, IDrawable
{
}
class PlayerGraphicComponent : IDrawableComponent
{
// Innenleben
}
Dein ComponentManager hält dann ein Array von den IDrawableComponent.
Gruß
t0ms3n
Hallo,
das casten an sich ist schon in Ordnung, allerdings solltest du den Fall berücksichtigen, dass der Cast auch schief gehen kann. Besser wäre also:
graphicComponent = _components[i] as Drawable;
if (graphicComponent != null)
graphicComponent.Draw(target, states);
Wenn deine Componenten-Objekte allerdings immer von beiden Interafaces ableiten sollen, dann solltest du wie von t0ms3n vorgeschlagen ein neues Interface definieren und deine Componenten davon ableiten.
Viele Grüße
Jens
Hey Leute!
Danke für die Tipps. Leider ist nur eines von den Componenten wirklich "Draw"-fähig bzw. Soll es sein. Daher möchte ich die Interfaces auseinander halten und den anderen nicht unnötig ein weiteres Verhalten aufzwingen was die nicht benötigen. Ich denke ich bleibe daher beim casten und sichere mich mit != ab 😃
Danke !
Hallo,
mir fällt da noch folgendes ein:
foreach (Drawable d in _components.OfType<Drawable>()) {
d.Draw(target, states);
}
sieht netter aus aber isses auch performanter? Nicht, dass das jetzt arg wichtig wäre - rein interessehalber.
Soweit ich weiss for > foreach (in performance)
Es ging nicht um das foreach sondern um das OfType 😃.
Du kannst natürlich dennoch einen for-Loop verwenden.
Soweit ich weiss for > foreach (in performance)
Pauschal ist das inkorrekt.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Es ging nicht um das foreach sondern um das OfType 😃.
Ah sorry hab ich überflogen - auch ne nette Weise 😄
Ich hatte dazu mal ein paar Testloops geschrieben
Mein Ergebnis war das "for" bei normalen Arrays schneller ist
"foreach" war z.B. bei einer List<> schneller
Noch was, solltet ihr irgendwann mal FxCop ( oder jetzt "Code Analysis" ) benutzen, fällt das
if (_components[i] is Drawable)
{
graphicComponent = (Drawable)_components[i];
graphicComponent.Draw(target, states);
}
Sowieso raus.
MS sieht in
graphicComponent = _components[i] as Drawable;
if (graphicComponent != null)
graphicComponent.Draw(target, states);
Den richtigen weg.