Je suis en train de faire un peu de XNA pour m’amuser et je suis tombé sur une erreur que je ne comprends pas.
J’ai créé une classe Sprite qui ressemble à ça, avec plus d’attributs :
[code]namespace MyFirstGame
{
class Sprite
{
private Texture2D texture;
private Vector2 position;
private Color tint = Color.White;
public Texture2D Texture
{
get { return texture; }
set { texture = value; }
}
public Vector2 Position
{
get { return position; }
set { position = value; }
}
public Color Tint
{
get { return tint; }
set { tint = value; }
}
public virtual void Update(GameTime gt) { }
public virtual void Draw(SpriteBatch sb)
{
sb.Draw(Texture, Position, Tint);
}
}
}[/code]
Le truc étrange c’est que quand j’essaie de faire ça :
Sprite monSprite = new Sprite();
monSprite.Position = new Vector2(1.0f, 1.0f);
monSprite.Position.X += 1.0f;
Je me ramasse une erreur du genre à la compilation:
Alors là je comprends pas trop. D’après mon code, Position correspond bien à une variable, vu que ça doit renvoyer la variable position. L’autre truc étrange c’est que ça ne me fait ça qu’avec les types Vector2. Je me suis dit que c’était peut-être que le paramètre X du type Vector2 n’était pas une variable, mais ça me semble bizarre et le message d’erreur a l’air de dire que c’est Position qui est une variable. Quelqu’un a une idée du soucis et de comment l’éviter?
Ah et encore un truc étrange, si j’ai un constructeur de ce type :
public Sprite(Vector2 position, Color tint)
{
Position = position;
Tint = tint;
}
C’est ptete parce que tu peux pas modifier .X tout seul (dans le cadre de XNA ca me paraitrait stupide, mais c’est souvent le cas avec GDI+). My two cents en attendant que qqu’un plus au fait que moi te réponde B)
Arf, oui bon ok, l’exemple est un peu foireux et j’ai oublié de créer une instance dans Position, mais le problème reste le même, c’est une erreur qui s’affiche à la compilation (le coup de la variable non initialisée ce serait à l’exécution que ça planterais).
Mais merci pour la remarque, je vais changer l’exemple.
Dans le même esprit, j’ai essayé de modifier de la même manière le paramètre « LevelOfDetail » de la même manière, et ça compile très bien.
[quote=“Micedre, post:5, topic: 46162”]Il ya quelque différence avec ce que tu as fait (entre autre le protected sur Vector2).
Maintenant ça peut être tout autre chose (oui j’aide beaucoup B) ), mais j’espère que ça pourra faire avancer le problème.[/quote]
En effet, je me suis inspiré entre autre de ce site pour faire le petit bout de programme montré ici, mais le problème ne vient pas du protected… d’ailleurs je ne comprends pas trop pourquoi il a utilisé protected comme visibilité et pas private comme les autres attributs.
Vector2 est un struct je suppose ?
Si c’est bien ça, il te faut faire le parrallèle avec le fait qu’une structure n’est pas un pointeur : elle est allouée sur le tas.
Du coup un { get; set; } renvoie UNE COPIE de ta variable.
[quote=“Styx31, post:7, topic: 46162”]Vector2 est un struct je suppose ?
Si c’est bien ça, il te faut faire le parrallèle avec le fait qu’une structure n’est pas un pointeur : elle est allouée sur le tas.
Du coup un { get; set; } renvoie UNE COPIE de ta variable.
Wow merci, c’est en effet ça le problème. Je savais pas que les struct fonctionnaient comme ça en C#.
Du coup, le seul moyen d’outrepasser le problème c’est bien de passer par une copie locale, modifier cette copie et repasser la copie modifiée, comme tu l’as fait dans ton exemple? Il n’y a pas une méthode un peu moins… “tordue”?
Oui, c’est exactement ce qu’il te faut faire : c’est le fonctionnement même des propriétés : tu ne sais pas ce que fait réellement le Get et le Set.
Si ca se trouve, ils changent d’autres variables de la classe en fonction des nouvelles valeurs de ton paramètre dans le set.
Si tu pouvais avoir accès directement à l’instance de Vector2, la classe instanciée par monSprite ne pourrait être au courant des changements de valeur. Le système de propriété permet d’être sur que l’on passe bien par ton traitement pour modifier la valeur.
Lorsque l’on utilise les propriétés, il faut bien avoir conscience de ce qu’il y a derrière (c’est à dire 2 méthodes, get_Property et set_Property).
PS: Une solution simple serait de créer une méthode .Offset(int x, int y) dans ta classe, comme c’est le cas dans Rectangle, afin de permettre à un appellant de modifier ton Location sans forcément passer par la recopie dans une variable.
He ouais, tu te fais griller tes occasions de defendre ton rang de « seg-fault mastah »… faut laisser place a la nouvelle generation B)
(enfin tu pourrais foutre un hack qui ajoute un delai de 8h a tous les posts mis sur seg-fault pendant la nuit)