IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Affectation inexpliquée de valeur par défaut sur classe fille


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de tribaleur
    Profil pro
    Développeur informatique
    Inscrit en
    Mai 2006
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2006
    Messages : 401
    Par défaut Affectation inexpliquée de valeur par défaut sur classe fille
    Bonjour,

    J'ai l'ensemble de classe "SpellEffect" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    public abstract class SpellEffect: IEquatable<SpellEffect> {
     
    	//_____ PRIVATE PROPERTIES _______________________________________________________________
    	protected Timer _duration = null;
    	protected bool _isStarted = false;
     
    	// ...
     
    	//_____ PUBLIC METHODES _______________________________________________________________
    	/* -------------------------------------------------------------------------------------------------------------------------
    	* Start the duration of the spell effect
    	* ------------------------------------------------------------------------------------------------------------------------- */
    	public void start () {
    		this._isStarted = true;
    		if (this._duration != null) {
    			this._duration.start();
    		}
    	}
     
    	// ...
    }
     
    [Serializable]
    public abstract class SpellEffect_Feature: SpellEffect {
    	// ...
    	public virtual float Value {
    		get {
    			float result = 0f;
     
    			if (this._isStarted && this._duration != null) {
    				if (!this._duration.IsUp && this.isUp()) {
    					this._iteration.start();
    					result = this.getCriticalValue(this._value);
    				}
    			}else if (this._isStarted) {
    				result = this.getCriticalValue(this._value);
    				// Set a timer to ended the spell Effect
    				this._duration = new Timer();
    			}
     
    			return result;
    		}
    	}
    	// ...
    }
     
    using SpellsNS;
    using System;
    using System.Collections.Generic;
     
    [Serializable]
    public class SpellEffect_Harmfull : SpellEffect_Feature {
    	//_____ ACCESSEURS _______________________________________________________________
    	public override float Value {
    		get { return -base.Value; }	
    	}
     
     
     
    	//_____ CONSTRUCTEURS _____________________________________________________________
    	public SpellEffect_Harmfull (string id, float value, string featureName, CriticalChance criticalChance = null, Element spellElement = null, List<FeatureRatio> featureRatios = null,
    								float duration = 0f, float iteration = 0.5f, SpellsEffectsList endEffects = null )
    		:base(id, value, featureName, spellElement, criticalChance, featureRatios, duration, iteration, endEffects, TargetedFeatureValue.CurrentValue){}
     
    	public SpellEffect_Harmfull (SpellEffect_Harmfull spellEffect_Harmfull) 
    		:base (spellEffect_Harmfull){}
     
    }
    J'ai également la classe "Timer" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
    using UnityEngine;
     
    [System.Serializable]
    public class Timer {
     
    	//_____ PRIVATE PROPERTIES _______________________________________________________________
    	private float _interval;
    	private bool _isUp = true;
    	private float _nextUp = 0f;
     
     
     
     
     
    	//_____ ACCESSEURS _______________________________________________________________
    	public bool IsUp {
    		get{			
    			// If the timer is not up, we check if it should be
    			if (!this._isUp && this._nextUp <= Time.time) { this._isUp = true; }
     
    			return this._isUp;
    		}
    	}
     
    	public float Interval {
    		get {	return this._interval; }
    		set {
    			//	The _interval can't have a negative value
    			if (value > 0) { this._interval = value; } 
    			else { this._interval = 0f; }
    			this.reset();
    		}
    	}
     
     
     
     
    	//_____ CONSTRUCTEURS _____________________________________________________________
    	public Timer (float interval = 0f) {
    		this.Interval = interval;
    	}
     
     
     
     
    	//_____ METHODES __________________________________________________________________
     
    	/* -------------------------------------------------------------------------------------------------------------------------
         * Set Up the next up time after "_interval" second
         * ------------------------------------------------------------------------------------------------------------------------- */	
    	public void start () {
    		if (this.IsUp && this._interval > 0f) {
    			this._isUp = false;
    			this._nextUp = Time.time + this._interval;
    		}
    	}
     
    	/* -------------------------------------------------------------------------------------------------------------------------
         * Return the remaining number of second before the next up
         * ------------------------------------------------------------------------------------------------------------------------- */
    	public float getRemainingSecond () {
    		float result = 0f;
    		if (!this.IsUp) { result = this._nextUp - Time.time; }
    		return result;
    	}
     
    	/* -------------------------------------------------------------------------------------------------------------------------
         * Reset the timer
         * ------------------------------------------------------------------------------------------------------------------------- */
    	 public void reset () {
    		this._isUp = true;
    		this._nextUp = 0f;
    	}
    }

    Lors de l'appel de la fonction "SpellEffect.start()", quand j'affecte la valeur "true" à la propriété "this._isStarted" ça initialise la propriété "this._duration" avec la valeur "new Timer()".
    Je ne comprends pas pourquoi car il n'y a aucune raison et que cette propriété avait la valeur "null" avant cette modification de valeur.

    Voici en image ce que ça donne dans mon debugueur :
    Au début de la fontion :
    Pièce jointe 432281

    Après l'affectation de valeur :
    Pièce jointe 432284

    En sachant que je suis en mode pas à pas et qu'il n'y a aucune étape de plus entre les deux.
    A savoir que le test "if (this._duration != null) {}" n'est pas encore exécutée car le débogueur vient juste de se positionner dessus.

    Avez-vous une idée du pourquoi du comment ?

    D'avance merci pour votre aide.

  2. #2
    Expert confirmé
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 427
    Par défaut
    Bonjour,
    J'avoue que je n'ai lu le code en entier.
    Mais je peux te donner une piste: tu rends toutes les propriétés private, et tu passes systématiquement par des accesseurs (y compris dans le code de la classe).
    Ainsi tu peux y mettre un point d'arrêt, et à chaque affectation tu pourras remonter la pile des appels.

    Tatayo.

  3. #3
    Membre éclairé Avatar de tribaleur
    Profil pro
    Développeur informatique
    Inscrit en
    Mai 2006
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2006
    Messages : 401
    Par défaut
    Bonjour,

    Merci pour ce retour. J'ai fait le test et malheureusement je n'ai pas plus d'info. J'ai bien mis un point d'arrêt sur l'appel de l'accesseur et j'ai bien mis la propriété en private. J'ai également remplacé tous les appel de la propriété directement par l'appel de l'accesseur. Même dans les classes filles.

    Entre ces deux deux lignes, l'accesseur n'est pas appelé.

    Je ne comprends vraiment pas.

    Pile d'appel avant :
    Nom : Pile D'appel 1.jpg
Affichages : 172
Taille : 105,9 Ko

    Pile d'appel après :
    Nom : Pile d 'appel 2.jpg
Affichages : 152
Taille : 97,5 Ko

    J'ai essayé de modifier mon code en rajoutant juste après l'instruction "this._duration = null" mais ça ne change rien :
    Nom : DurationIsNull.jpg
Affichages : 178
Taille : 35,5 Ko



    Petites précisions :
    -Je suis sur mon environnement avec Unity3d. Même si ma classe mère n'utilise que des bibliothèques .net.
    -L'objet actuel est une deepCopy d'un autre "SpellEffect" via sérialisation.

    Voici l'appel de la deepCopy :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tempSpellEffect = DeepCopy.Clone(currentSpellEffect);
    Voici ma classe de DeepCopy :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    using System;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.IO;
     
    public class DeepCopy {
    	//_____ METHODES ____________________________________________________________
    	/* -------------------------------------------------------------------------------------------------------------------------
         * Return a deep copy of the paraméter object
         * ------------------------------------------------------------------------------------------------------------------------- */
    	public static T Clone<T>(T source) {
    		// Check the argument compatibility
    		if (!typeof(T).IsSerializable){ throw new ArgumentException("The type must be serializable.", "source"); }
     
    		// Don't serialize a null object, simply return the default for that object
    		if (Object.ReferenceEquals(source, null)) { return default(T); }
     
    		IFormatter formatter = new BinaryFormatter();
    		Stream stream = new MemoryStream();
     
    		// Release the memory allocated to the stream when
    		using (stream) {
    			formatter.Serialize(stream, source);
    			stream.Seek(0, SeekOrigin.Begin);
    			return (T)formatter.Deserialize(stream);
    		}
    	}
    }
    *** EDIT : ***
    J'ai essayé d'exclure la deepCopy comme source potentielle de problème et voici ce que ça donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    tempSpellEffect = DeepCopy.Clone(currentSpellEffect); 
    tempSpellEffect.Start();// Appel actuel, bug présent
    
    // A priori la DeepCopy n'influence en rien le bug
    tempSpellEffect =currentSpellEffect;
    tempSpellEffect.Start();// Bug présent également
    
    tempSpellEffect =DeepCopy.Clone(currentSpellEffect);
    currentSpellEffect.Start();// Bug présent également

  4. #4
    Expert confirmé
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 427
    Par défaut
    Je disais de mettre le point d'arrêt DANS l'accesseur (dans le setter, plus précisément), pas au niveau des appels.
    Ainsi tu sera "averti" en cas d'affectation, quelle qu'en soit l'origine.

    Tatayo.

  5. #5
    Membre éclairé Avatar de tribaleur
    Profil pro
    Développeur informatique
    Inscrit en
    Mai 2006
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2006
    Messages : 401
    Par défaut
    Je l'ai fait en parallèle des points d'arrêts qui sont au niveau de l'appel.
    Et comme je le disais, aucune appel du setter n'est fait au moment du changement de valeur de ma propriété.

    D'ailleurs, à aucun moment dans mon code je ne passe par ce setter quand je ne redéfini pas ma propriété dans le constructeur de ma classe. Et dans le cas présent je ne le fait pas.

    Mon point d'arrêt dans le setter ne se déclenche du coup jamais.
    Etant donné que ma propriété est maintenant private, je ne peux pas y accéder depuis l'extérieur de ma classe. Et j'ai réalisé un chercher remplacer dans toutes mes classes filles pour modifier l'appel de la propriété. De toute façon, si j'avais encore des appels directs VS me sortirai une erreur.

    Ce qui m'interpelle particulièrement c'est le fait que si je réassigne la valeur null à la propriété, cela ne change pas sa valeur.

    J'ai essayé de redémarrer mon ordi aussi au cas où mais ça ne change rien. Je n'ai pas encore pus essayer sur un autre poste pour le moment.

    Merci de ton aide en tous cas.

  6. #6
    Membre éclairé Avatar de tribaleur
    Profil pro
    Développeur informatique
    Inscrit en
    Mai 2006
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2006
    Messages : 401
    Par défaut
    Pour détecter l'origine du problème, j'ai décidé de commenter tous les appels à l'accesseur dans mon code.
    Suite à ça le changement de valeur ne se fait plus sur la propriété.
    Du coup j'ai pus remonter jusqu'à l'accesseur Value de la classe fille SPellEffect_Feature. J'ai mis des point d'arrêts dessus et mon pas à pas ne s'arrête jamais dessus. Mais si je commente la ligne ci-dessous en gras, le problème ne se produit plus.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public virtual float Value {
    		get {
    			float result = 0f;
     
    			if (this.IsStarted && this._duration != null) {
    				if (!this._duration.IsUp && this.isUp()) {
    					this._iteration.start();
    					result = this.getCriticalValue(this._value);
    				}
    			}else if (this.IsStarted) {
    				result = this.getCriticalValue(this._value);
    				// Set a timer to ended the spell Effect
    				// this._duration = new Timer();
    			}
     
    			return result;
    		}
    	}
    Je ne m'explique toujours pas cependant comment la modification de la valeur de la propriété "_isStarted" peut appeler cet accesseur.
    Je suis en train de regarder ce point.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Valeur Par défaut sur une Combobox attaché à une collection
    Par olufade dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 26/08/2009, 17h47
  2. valeur par défaut sur une jointure
    Par pedro99 dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 26/06/2008, 08h50
  3. Valeur par défaut sur ouverture formulaire
    Par Sami Xite dans le forum IHM
    Réponses: 6
    Dernier message: 26/12/2006, 11h08
  4. Réponses: 1
    Dernier message: 25/09/2006, 09h50
  5. [MySQL] Valeur par défaut sur un SELECT
    Par hugo69 dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 16/01/2006, 17h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo