Minotthor
Messages postés72Date d'inscriptionvendredi 16 mai 2003StatutMembreDernière intervention12 août 2009
-
26 juil. 2009 à 22:55
Minotthor
Messages postés72Date d'inscriptionvendredi 16 mai 2003StatutMembreDernière intervention12 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 ?
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 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 :)
Minotthor
Messages postés72Date d'inscriptionvendredi 16 mai 2003StatutMembreDernière intervention12 août 20092 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 ?