[Résolu][C#] Erreur de compilation étrange

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; }

Ca passe très bien la compilation…

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)

Vector2 n’est pas un type primitif. Il a besoin d’être initialisé donc dans ton constructeur par défaut, tu dois créer une instance de Position.

genre

public Sprite() { Position = new Vector2(); }

et cela vaut pour tous tes attributs non-primitifs. Les membres non-statiques sont initialisés à null en C#.

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.

monSprite.Texture.LevelOfDetail = 12;

Bon, avant toutes choses, je n’y connais vraiment pas grand chose en C# mais ça m’intéresse.

En essayant de comprendre ce que faisais ton code, je suis tombé sur cette page:
http://www.ziggyware.com/print.php?type=A&item_id=131

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=“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.

Donc monSprite.Position.X = 5 équivaudrait à :

Vector2 truc = monSprite.Position; truc.X = 5; monSprite.Position = truc;

Il ya des jours ou je me dis que je suis bien content de bosser en anglais… B)

[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.

Donc monSprite.Position.X = 5 équivaudrait à :

Vector2 truc = monSprite.Position; truc.X = 5; monSprite.Position = truc;[/quote]

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”?

Pour plus d’infos, tu peux aller lire la fin de cette page

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.

Oki, j’ai bien compris. En effet expliqué comme ça c’est tout à fait logique.

Merci beaucoup pour l’article et toutes les explications. Me coucherait moins bête ce soir B).

C’est fort, Styx il dechire en journee, je vais dormir, je reviens y a des problemes poses et resolu dans la foulee.

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)