Initialisations "Array-like", IEnumerable, Add() et lecture seule

Résolu
Minotthor Messages postés 72 Date d'inscription vendredi 16 mai 2003 Statut Membre Dernière intervention 12 août 2009 - 26 juil. 2009 à 22:55
Minotthor Messages postés 72 Date d'inscription vendredi 16 mai 2003 Statut Membre Dernière intervention 12 août 2009 - 28 juil. 2009 à 00:34
Bonjour à tous,

Soient Assembly et Sign, deux classes "maison" ...

Je crée une classe Assembly qui contiendra en privé une List<Sign> et j'aimerais pouvoir initialiser ma classe "Assembly à la façon des tableaux, c'est-à-dire par exemple :
Assembly = new Assembly() { Square, Tau, Disjonction, Negation };

Ma première question porte sur l'interface exigée pour une telle initialisation. Il est est requis que la class Assembly implémente IEnumerable et éventuellement IEnumerable<Sign> alors que, en pratique, aucun énumérateur ne sera demandé à ma classe. J'ai même pu écrire mes méthodes de cette façon sans qu'aucune exception ne soit soulevée car ces méthodes ne sont pas appelées par l'initialisation :
IEnumerator IEnumerable.GetEnumerator()
{throw new NotSupportedException();}
IEnumerator<Sign> IEnumerable<Sign>.GetEnumerator()
{throw new NotSupportedException();}
De surcroît, le compilateur exige que ma classe présente une méthode Add(object value) alors que ce n'est requis ni par l'interface IEnumerable, ni par l'interface IEnumerable<Sign>. Je suis un peu perdu. Comment expliquer toutes ces bizarreries ? Est-ce que je passe à côté de quelque chose ?

Ma seconde question est plus pragmatique : elle porte sur la possibilité de placer en lecture seule une classe initialisée de la sorte, c'est-à-dire de lever une exception NotSupportedException si la méthode Add(object value) est appelée après l'initialisation. C'est par exemple ce que fait la classe Array du Framework .NET. Il est permis de l'initialiser en "{}"; je suppose donc qu'à cet instant précis sa méthode Add(object value) est utilisable. Immédiatement après, tout appel à la méthode lève une NotSupportedException comme spécifié dans la documentation. Comment reproduire un tel comportement ? Plus spécifiquement, comment puis-je savoir que l'initialisation en "{}" de mon objet est terminée pour passer à true un private bool ReadOnly qui sera contrôlé par Add(object value) pour lever une NotSupportedException et empêcher ainsi l'utilisateur de Assembly d'ajouter de nouveaux Sign ?

En vous remarciant,
Mathieu.
A voir également:

4 réponses

cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
27 juil. 2009 à 12:23
Bonjour,
Voici un exemple de code:

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Assembly<Sign> a = new Assembly<Sign>()
            {
                new Sign(),
                new Sign()
            };
        }
    }

    public class Sign { }

    public class Assembly<T> : IEnumerable<T>
    {
        private List<T> _signs = new List<T>();

        public Assembly()
        {
        }

        public void Add(T t)
        {
            this._signs.Add(t);
        }

        public IEnumerator<T> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }
}


La création d'objet en utilisant ce genre d'initialisation est simplement un sucre synthaxe. Une fois compiler, c'est la méthode Add de la classe qui sera appelée, c'est pour cela qu'il faut absolument implémentée IEnumerable, car il expose cette méthode.

Il en expose également d'autres, comme GetEnumerator que tu mentionnes. Tu peux laisser le corps de cette méthode vide, par contre, si celle-ci doit être appelée, elle ne retournera bien entendu pas le comportement voulu. Tu peux faire un teste en effectuant un foreach sur ta collection de Sign (qui, en interne, appelle justement cette méthode GetEnumerator...).

J'espère que c'est le chose sont maintenant un peu plus clair :)


[hr]
-Blog-
-Site Perso-
3
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
27 juil. 2009 à 22:18
Bonne question... j'avais jamais fait attention...
Réponse ici

[hr]
-Blog-
-Site Perso-
3
Minotthor Messages postés 72 Date d'inscription vendredi 16 mai 2003 Statut Membre Dernière intervention 12 août 2009 2
27 juil. 2009 à 21:51
Je te remercie pour tes explications. J'ai testé ma classe au foreach et effectivement cela déclenché une série d'Exceptions.

Par contre, je ne vois toujours pas dans la documentation où IEnumerable exposerait la méthode void Add(object). Elle ne fait pas partie des membres de l'interface. Ca sent un peu la bidouille tout ça, nan ?

Personne n'aurait une idée pour ma seconde question ?
0
Minotthor Messages postés 72 Date d'inscription vendredi 16 mai 2003 Statut Membre Dernière intervention 12 août 2009 2
28 juil. 2009 à 00:34
Article très intéressant.

Encore merci.
0
Rejoignez-nous