Lignes de code VB Net identiques

Résolu
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 - 22 nov. 2022 à 03:13
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 - 22 nov. 2022 à 17:51

Bonjour

Dans un de mes projets j'ai la ligne de code suivante 

ListLettresDeplacement.Remove(ListLettresDeplacement.Last)

rien de bien compliqué : on supprime le dernier élément de  ListLettresDeplacement . Or avec cette ligne j'ai toujours un bug dans le projet .

Après pas mal de recherche dans l'algorithme du code je n'ai trouvé aucun remède et la logique du code était correcte .

J'ai remplacé cette ligne par celle-ci en dessous et là miracle : plus aucun bug !  

ListLettresDeplacement.RemoveAt(ListLettresDeplacement.Count - 1)

Pourtant d'après mes connaissances ces 2 lignes devraient faire la même chose . Quelqu'un peut-il me dire ce que j'ai loupé ? Je précise qu'avec la première ligne l'importation de System.Linq était faite .

Merci pour les réponses !  


7 réponses

vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
Modifié le 22 nov. 2022 à 06:10

Après réflexion je me réponds à moi-même mais sans certitude

Soit par exemple une liste d'entiers ( integer en langage VB Net ) :  12  7   9  14  8  24  9

ListLettresDeplacement.Remove(ListLettresDeplacement.Last)

 Cette ligne supprime un élément dont la valeur est ListLettresDeplacement.Last . Cette valeur est = à 9 . Or cette ligne de code supprime dans la liste le premier 9 qu'elle trouvera . Donc la liste deviendra 12  7  14  8  24  9 . Le 9 en troisième position ( indice 2 de la liste ) a disparu . Ce qui n'est pas le résultat attendu . Notez que le problème ne se pose pas si la liste ne contient que des éléments distincts ( exemple 12 7 9 14 8 24 15 ) et dans mon projet la liste contient pas que des éléments distincts . Une même valeur peut être présente plusieurs fois dans ma liste .

Par contre 

ListLettresDeplacement.RemoveAt(ListLettresDeplacement.Count - 1)

supprimera bien le dernier élément de la liste sans se soucier de sa valeur . La liste devient  12  7  9  14  8  24 . Le 9 en dernier a été supprimé .

Quelqu'un peut-il me dire si mon raisonnement est juste ?

Merci


0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
22 nov. 2022 à 04:24

Etant curieux j'ai fait un projet de test . Et ma réflexion est plus que correcte . Et ceci est aussi valable en C# .

Je mets en résolu ( en souhaitant que cela puisse servir à un membre ) .


0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
22 nov. 2022 à 08:58

Bonjour 

il faut que je fasse des tests, et je n'aurais peut-être pas le temps dans la journée.

Mais je pense que ton raisonnement n'est pas correct. Ou en tout cas, pas pour les int.

0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
Modifié le 22 nov. 2022 à 09:22

Bonjour Whismeril 

Merci d'avoir mis le message dans le bon forum ( je n'ai pas fait attention )

Mon programme de test a été fait avec des List(of Integer) 

Une Form avec 2 boutons nommé ButtonRemove et ButtonRemoveAt 

voici le code

Public Class Form1

    Private ListInteger1, ListInteger2 As List(Of Integer)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        ListInteger1 = New List(Of Integer) From {10, 12, 9, 14, 27, 18, 15, 9}
        ListInteger2 = New List(Of Integer) From {10, 12, 9, 14, 27, 18, 15, 9}

    End Sub

    Private Sub ButtonRemove_Click(sender As Object, e As EventArgs) Handles ButtonRemove.Click

        ListInteger1.Remove(ListInteger1.Last) ' Résultat : 10  12  14  27  18  15  9

    End Sub

    Private Sub ButtonRemoveAt_Click(sender As Object, e As EventArgs) Handles ButtonRemoveAt1.Click

        ListInteger2.RemoveAt(ListInteger2.Count - 1) ' Résultat : 10  12  9  14  27  18  15

    End Sub

End Class

En mettant 2 points d'arrêt sur les End Sub des 2 boutons et en regardant les valeurs de la List(of Integer) associée au bouton on voit que ce n'est pas le même 9 qui est supprimé


0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
22 nov. 2022 à 11:24

Oui, en effet, mal réveillé je n'ai pas fair attention au AT de RemoveAt et  j'ai pensé, sans vérifier, qu'il devait y avoir au moins 2 surcharges et que celle qui prend un int en paramètre doit  traiter l'index et non l'item.

Donc erreur de ma part.

Cela dit, ton raisonnement reste incomplet, je présentais une comportement dependant du type, et c'est le cas.

	            //D'abord des types valeurs
            List<int> lesints = new List<int> { 10, 12, 9, 14, 27, 18, 15, 9 }; //int type valeur
            List<bool> lesbools = new List<bool> { true, true, false, true, true, true, true, false }; //bool type valeur

...

            lesints.Remove(lesints.Last());
            lesbools.Remove(lesbools.Last());

       
 

Là OK c'est bien la première valeur correspondante qui est supprimée.

Mais avec un type référence?

class MonInt
    {
        public MonInt(int LeInt)
        {
            Valeur = LeInt;
        }

        public int Valeur { get; set; }

        public override string ToString()
        {
            return Valeur.ToString();
        }
    }




	            //D'abord des types valeurs
            List<int> lesints = new List<int> { 10, 12, 9, 14, 27, 18, 15, 9 }; //int type valeur
            List<bool> lesbools = new List<bool> { true, true, false, true, true, true, true, false }; //bool type valeur

            //ensuite la classe MonInt avec 2 cas,
            //  des instances toutes différente
            //  une instance en double
            List<MonInt> mesints = lesints.Select(i => new MonInt(i)).ToList(); //MontInt type référence
            List<MonInt> mesIntsAvecDoublon = new List<MonInt> { mesints[0], mesints[1], mesints.Last(), mesints[3], mesints[4], mesints[5], mesints[6], mesints.Last() }; //MonInt type valeur avec 2 fois la même instance

...

            lesints.Remove(lesints.Last());
            lesbools.Remove(lesbools.Last());

            mesints.Remove(mesints.Last());
                mesIntsAvecDoublon.Remove(mesIntsAvecDoublon.Last());


 

OK, donc là c'est bien la première référence correspondante qui est supprimée.

PS: je continue sur un autre message, l'éditeur commence à bugger sur l'ipad


0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
22 nov. 2022 à 11:37

Et avec string, qui est un type référence , mais se comporte souvent comme un type valeur,

	        //D'abord des types valeurs
            List<int> lesints = new List<int> { 10, 12, 9, 14, 27, 18, 15, 9 }; //int type valeur
            List<bool> lesbools = new List<bool> { true, true, false, true, true, true, true, false }; //bool type valeur

            //ensuite la classe MonInt avec 2 cas,
            //  des instances toutes différente
            //  une instance en double
            List<MonInt> mesints = lesints.Select(i => new MonInt(i)).ToList(); //MontInt type référence
            List<MonInt> mesIntsAvecDoublon = new List<MonInt> { mesints[0], mesints[1], mesints.Last(), mesints[3], mesints[4], mesints[5], mesints[6], mesints.Last() }; //MonInt type valeur avec 2 fois la même instance

            //avec des string, les string ne sont pas des types valeurs...
            List<string> lestrings = lesints.Select(i => i.ToString()).ToList(); //string pas type valeur

...


            lesints.Remove(lesints.Last());
            lesbools.Remove(lesbools.Last());

            mesints.Remove(mesints.Last());
            mesIntsAvecDoublon.Remove(mesIntsAvecDoublon.Last());

            lestrings.Remove(lestrings.Last());
            var interfaces = typeof(string).GetInterfaces();

Ben là, c'est la première valeur correspondante qui est supprimée....

Pourquoi cette différence ?

Parmi les hypothèses, le fait que string implémente icomparable ou que le == soit surchargé 

class MonIntComparable : MonInt, IComparable
    {
        public MonIntComparable(int LeInt) : base(LeInt) { }

        public int CompareTo(object obj)
        {
            return Valeur.CompareTo(((MonIntComparable)obj).Valeur);
        }
    }

    class MonIntEgalEgal : MonInt
    {
        public MonIntEgalEgal(int LeInt) : base(LeInt) { }

        public static bool operator == (MonIntEgalEgal un, MonIntEgalEgal autre)
        {
            return un.Valeur == autre.Valeur;
        }

        public static bool operator !=(MonIntEgalEgal un, MonIntEgalEgal autre)
        {
            return !(un == autre);
        }
    }
	
	
	
	
	            //D'abord des types valeurs
            List<int> lesints = new List<int> { 10, 12, 9, 14, 27, 18, 15, 9 }; //int type valeur
            List<bool> lesbools = new List<bool> { true, true, false, true, true, true, true, false }; //bool type valeur

            //ensuite la classe MonInt avec 2 cas,
            //  des instances toutes différente
            //  une instance en double
            List<MonInt> mesints = lesints.Select(i => new MonInt(i)).ToList(); //MontInt type référence
            List<MonInt> mesIntsAvecDoublon = new List<MonInt> { mesints[0], mesints[1], mesints.Last(), mesints[3], mesints[4], mesints[5], mesints[6], mesints.Last() }; //MonInt type valeur avec 2 fois la même instance

            //avec des string, les string ne sont pas des types valeurs...
            List<string> lestrings = lesints.Select(i => i.ToString()).ToList(); //string pas type valeur

            //avec la classe MonIntComparable
            List<MonIntComparable> mesintsComparables = lesints.Select(i => new MonIntComparable(i)).ToList(); //MontInt type référence, Comparable

            //avec la classe MonIntEgalEgal
            List<MonIntEgalEgal> mesintsEgalEgal = lesints.Select(i => new MonIntEgalEgal(i)).ToList(); //MontInt type référence, dont les opérateurs == et != sont surchargés

            lesints.Remove(lesints.Last());
            lesbools.Remove(lesbools.Last());

            mesints.Remove(mesints.Last());
            mesIntsAvecDoublon.Remove(mesIntsAvecDoublon.Last());

            lestrings.Remove(lestrings.Last());
            var interfaces = typeof(string).GetInterfaces();

            mesintsComparables.Remove(mesintsComparables.Last());

            mesintsEgalEgal.Remove(mesintsEgalEgal.Last());


 


Et du coup, non,  on ne dirait pas.

Bref, la conclusion c'est que ça dépend du type et que méfiance, il y a au moins un cas qui frait exception.
 


0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
Modifié le 22 nov. 2022 à 16:36

Très intéressant ton exposé !

En tout cas le principal c'est que dans mon projet je n'ai plus de bug .

Merci


0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
22 nov. 2022 à 17:51

:)


0
Rejoignez-nous