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

Contribuez .NET Discussion :

[Source] Un petit compteur


Sujet :

Contribuez .NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Par défaut [Source] Un petit compteur
    Bon jour à tous,
    peut-être que ce sera utile à certains...
    C'est un petit compteur qui permet d'attribuer un numero à un objet. Si l'objet est supprimé, le numéro sera mis dans une pile qui sera trié, puis le plus petit sera réalloué ensuite.
    Typiquement, je crée un singleton du compteur, j'appelle la méthode pour allouer le numéro dans le constructeur, et la méthode pour le désallouer quand je n'ai plus besoin de l'objet (Dans le dispose par exemple).
    Si c'est inutile, je mettrai le poste en délestage...
    La classe du compteur :
    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
     
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;
     
    namespace Counter
    {
        /// <summary>
        /// Cette classe permet de créer un compteur d'instance d'un type d'objet particulier, qui gére la suppression et la redistribution des numéros d'instances.
        /// </summary>
        /// <typeparam name="T">Le type de l'objet</typeparam>
        public class InstanceCounter<T>
        {
     
            //L'arraylist contenant les numéros d'instances désalloués
            private ArrayList counterQueue = new ArrayList();
            //Dictionnaire contenant l'insatnce liée à son numéro d'instance
            private Dictionary<T, int> dictionary = new Dictionary<T, int>();
            private int counter = 0;
     
            /// <summary>
            /// Permet de faire commencer le compteur à la valeur souhaitée.
            /// </summary>
            public int SetCounter
            {
                set { counter = value; }
            }
     
            /// <summary>
            /// Constructeur
            /// </summary>
            public InstanceCounter()
            {
            }
     
            /// <summary>
            /// Permet de créer ou d'obtenir (si l'instance est déjà référencée) le numéro d'instance d'un objet.
            /// </summary>
            /// <param name="anObject">Un Objet du type déclaré</param>
            /// <returns>Le numéro d'instance</returns>
            public int CreateOrGetInstanceNumber(T anObject)
            {
                int instanceNumber;
                //L'objet est-il présent dans le dictionnaire? S'il l'est, on restitue son numéro.
                if (dictionary.ContainsKey(anObject))
                {
                    dictionary.TryGetValue(anObject, out instanceNumber);
                }
                else
                {
                    //La queue des numéros d'instances supprimés est-elle vide ou pleine? Si oui, on incrémente le compteur.
                    if (counterQueue.Count == 0 || counterQueue.Count == counterQueue.Capacity)
                    {
                        instanceNumber = ++counter;
                    }
                    // Sinon, on trie la queue afin de redistribuer le plus petit numéro d'instance.
                    else
                    {
                        counterQueue.Sort();
                        instanceNumber = (int)counterQueue[0];
                        //Onsupprime le plus petit élément de la queue.
                        counterQueue.RemoveAt(0);
                    }
                    //On référence l'objet et son numéro d'instance.
                    dictionary.Add(anObject, instanceNumber);
                }
                //On retourne le numéro d'instance
                return instanceNumber;
            }
     
            /// <summary>
            /// Permet de désouscrire le numéro d'instance d'un objet, et de l'ajouter à la pile de redistribution.
            /// </summary>
            /// <param name="anObject">Un objet du type déclaré</param>
            public void DeleteInstanceNumber(T anObject)
            {
                int instanceNumber;
                //Si le dictionnaire contient l'objet
                if (dictionary.ContainsKey(anObject))
                {
                    dictionary.TryGetValue(anObject, out instanceNumber);
                    //On ajoute le numéro d'instance à la queue
                    counterQueue.Add(instanceNumber);
                    //On supprime la référence du dictionnaire
                    dictionary.Remove(anObject);
                }
            }
     
            /// <summary>
            /// Permet de vider la queue des numéros d'instances devant-être réatribuée.
            /// </summary>
            public void ReInitializeInstanceQueue()
            {
                counterQueue.Clear();
            }
     
            /// <summary>
            /// Permet de connaître le nombre de numéros d'instances présent dans la queue de redistribution.
            /// </summary>
            /// <returns>Le nombre de numéros d'instances présents dans la queue </returns>
            public int GetNumberOfInstancesInQueue()
            {
                return counterQueue.Count;
            }
     
            /// <summary>
            /// Permet de fixer le nombre maximum de numéros d'instances d'objets à conserver.
            /// </summary>
            /// <param name="max">Le nombre de numéro d'instances à conserver.</param>
            public void SetMaximumInstanceQueue(int max)
            {
                //Le nombre de numéros d'instances en attente est-il inférieur à la valeur?
                if (GetNumberOfInstancesInQueue() > max)
                {
                    throw new ArgumentOutOfRangeException();
                }
                //On modifie la capacité de la queue
                else
                {
                    counterQueue.Capacity = max;
                }
            }
        }
    }
    La classe du singleton :
    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
    using System;
    using System.Text;
    using System.Collections;
     
    namespace Counter
    {
        /// <summary>
        /// Assure l'unicité du compteur grâce à l'utilisation d'un singleton.
        /// </summary>
        /// <typeparam name="T">Le type du compteur.</typeparam>
        public class SingletonInstanceCounter<T>
        {
     
            private static InstanceCounter<T> singleton = null;
            private static readonly object padLock = new object();
     
            /// <summary>
            /// Constructeur privé du singleton.
            /// </summary>
            private SingletonInstanceCounter()
            {
            }
     
            /// <summary>
            /// Permet de créer ou d'accèder à l'instance unique du compteur.
            /// </summary>
            /// <returns>L'instance unique du compteur</returns>
            public static InstanceCounter<T> getInstance()
            {
                lock (padLock)
                {
                    if (singleton == null)
                    {
                        singleton = new InstanceCounter<T>();
                    }
                    return singleton;
                }
            }
        }
    }

  2. #2
    Rédacteur
    Avatar de SaumonAgile
    Homme Profil pro
    Team leader
    Inscrit en
    Avril 2007
    Messages
    4 028
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Team leader
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2007
    Messages : 4 028
    Par défaut
    Ton singleton pourrait avantageusement être réécrit de cette manière :

    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
    public sealed class $ClassName$
    {
        $ClassName$()
        {
        }
     
        public static $ClassName$ Instance
        {
            get
            {
                return Interne.instance;
            }
        }
     
        class Interne
        {
            // Pour le compilateur, cela évite que l'instance soit créée avant le premier accès.
            static Interne()
            {
            }
     
            internal static readonly $ClassName$ instance = new $ClassName$();
        }
    }
    Besoin d'un MessageBox amélioré ? InformationBox pour .NET 1.1, 2.0, 3.0, 3.5, 4.0 sous license Apache 2.0.

    Bonnes pratiques pour les accès aux données
    Débogage efficace en .NET
    LINQ to Objects : l'envers du décor

    Mon profil LinkedIn - MCT - MCPD WinForms - MCTS Applications Distribuées - MCTS WCF - MCTS WCF 4.0 - MCTS SQL Server 2008, Database Development - Mon blog - Twitter

  3. #3
    Membre chevronné
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Par défaut
    // Pour le compilateur, cela évite que l'instance soit créée avant le premier accès.
    Je connaissais pas l'astuce. Merci. Je vais modifier demain si j'ai le temps.

  4. #4
    Membre éprouvé Avatar de Nikoui
    Inscrit en
    Décembre 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Décembre 2007
    Messages : 119
    Par défaut
    Citation Envoyé par SaumonAgile Voir le message
    Ton singleton pourrait avantageusement être réécrit de cette manière [...]
    Juste pour mon info, en quoi est-ce plus avantageux ?

  5. #5
    Rédacteur
    Avatar de SaumonAgile
    Homme Profil pro
    Team leader
    Inscrit en
    Avril 2007
    Messages
    4 028
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Team leader
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2007
    Messages : 4 028
    Par défaut
    Complètement Thread-Safe + Lazy loading
    Besoin d'un MessageBox amélioré ? InformationBox pour .NET 1.1, 2.0, 3.0, 3.5, 4.0 sous license Apache 2.0.

    Bonnes pratiques pour les accès aux données
    Débogage efficace en .NET
    LINQ to Objects : l'envers du décor

    Mon profil LinkedIn - MCT - MCPD WinForms - MCTS Applications Distribuées - MCTS WCF - MCTS WCF 4.0 - MCTS SQL Server 2008, Database Development - Mon blog - Twitter

  6. #6
    Membre éprouvé Avatar de Nikoui
    Inscrit en
    Décembre 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Décembre 2007
    Messages : 119
    Par défaut
    Bah l'implémentation proposée au dessus aussi est thread safe, non ? Quand au lazy loading, là aussi le singleton n'est instancié qu'au premier appel. Je ne vois pas trop la différence en fait (quand au résultat obtenu, sur la manière c'est en effet 2 approches distinctes)

  7. #7
    Rédacteur
    Avatar de SaumonAgile
    Homme Profil pro
    Team leader
    Inscrit en
    Avril 2007
    Messages
    4 028
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Team leader
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2007
    Messages : 4 028
    Par défaut
    L'implémentation que je propose est intrensèquement thread-safe, nul besoin de passer par un lock (qui "verrouille" la variable).
    Quant au lazy loading, la classe interne ne sera pas initialisée avant le premier accès, alors que dans l'implémentation initiale, ce n'est que l'instance qui n'est pas initialisée avant le premier accès. Tu saisis la nuance ou ce n'est pas clair ?
    Besoin d'un MessageBox amélioré ? InformationBox pour .NET 1.1, 2.0, 3.0, 3.5, 4.0 sous license Apache 2.0.

    Bonnes pratiques pour les accès aux données
    Débogage efficace en .NET
    LINQ to Objects : l'envers du décor

    Mon profil LinkedIn - MCT - MCPD WinForms - MCTS Applications Distribuées - MCTS WCF - MCTS WCF 4.0 - MCTS SQL Server 2008, Database Development - Mon blog - Twitter

Discussions similaires

  1. Code Source D'un Compteur De Visites
    Par Thomas92100 dans le forum Statistiques
    Réponses: 6
    Dernier message: 08/04/2011, 10h44
  2. petit compteur en jsp
    Par ajor dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 17/09/2008, 10h44
  3. un petit prob de compteur
    Par visualk dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 11/05/2007, 15h48
  4. [Source] Un petit jeu de mémoire
    Par luckyvae dans le forum Contribuez
    Réponses: 2
    Dernier message: 03/01/2007, 18h37
  5. Réponses: 8
    Dernier message: 12/06/2006, 22h40

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