8
votes

Comment puis-je détecter ajoute à une liste générique en C # 4.0?

J'ai une sous-classe de Liste appelé locationlist . Ceci est un moyen pratique pour nous d'ajouter d'autres propriétés (comme isexpandedd et de telle que nous pouvons utiliser dans l'interface utilisateur. BON assez. Mais maintenant, nous voulons que chaque emplacement soit conscient de son parent. En tant que tel , nous devons être notifiés lorsque quelque chose est ajouté à la liste de localisation, mais vous ne pouvez pas remplacer ajouter et supprimer . Pendant que nous pouvons utiliser Observablecollection, c'est plus d'une vue / viewmodel construire. Ce sont des données de modèle pures.

Bien sûr, nous pourrions définir manuellement le parent lorsque vous l'ajoutez à la collection, mais je déteste la logique non automatisée comme celle-ci, car il n'y a rien à appliquer correctement. Laisser la collection (bien, la liste) disent automatiquement "hé ... tu es ajouté, je vais donc mettre votre parent à la classe qui me possède." Est ce que je suis après.

Ma pensée est à au lieu de la sous-classe List Pour simplement créer une classe droite qui utilise une liste Liste Interne, puis je peux simplement exposer Mes propres ajout / supprimer des méthodes et gérer les ajustements à «parent» de là. Cependant, ce faisant des casse-croûtes pour pouvoir énumérer sur la collection interne puisqu'il est à l'intérieur.

Cela dit, est-il un moyen d'écouter les modifications apportées à la liste ou au moins déléguer son interface iEnumerable de l'objet emballé sur son enveloppe?


0 commentaires

6 Réponses :


4
votes

Liste a des membres protégés insertItem , removeItem etc. que vous pouvez remplacer dans votre classe dérivée vers Faites ce que vous voulez.

** Mise à jour **

En réalité, ce qui précède est incorrect, c'est collection qui a ces méthodes protégées. En général, lors de la dérive des classes de liste personnalisées, il est recommandé de dériver à partir de Collection plutôt que . .

voir Cette réponse .


6 commentaires

Si vous allez remplacer insertItem / removeItem, pourquoi n'utilisez-vous pas simplement une version où le travail est déjà effectué (observablecollection)


Observablecollection est vraiment optimisé davantage pour la viewModel que le modèle. La seule personne qui doit être consciente du changement est la collection elle-même. Vous n'avez pas besoin de la génération de notification de changement complet.


@Marqueiv: "Je ne peux même pas accepter votre réponse pour une autre onze minutes" - tout aussi bien que la réponse initiale était fausse - trop rapide de la marque. Voir la mise à jour et acceptez la réponse de Michael Stum!


@Joe, j'ai peut-être parlé trop tôt. Je ne vois pas l'un ou l'autre de ces objets sont proposés dans l'intellisense pour la liste , ni je le vois dans les docs. Êtes-vous sûr que c'est la bonne classe? ( msdn.microsoft.com/en-us /Library/6Sh2ey19.aspx )


@Joe, je vois ceux qui sont sur la collection , pas la liste . Était-ce ce que tu voulais dire?


@Joe, déjà eu! :) Néanmoins ... da * n J'aime à quelle vitesse la communauté peut aider un gars à 1 heure du matin. :) Presque aussi vite que de googler ce genre de choses, sauf avec des personnes réelles pour discuter des pièges et des mises en garde au lieu de simplement des pages reliées qui peuvent ou non correspondent.



9
votes

Changez votre liste de localisation pour hériter de Collection à la place. Je ne sais pas pourquoi Liste n'est pas scellé, mais ce n'est pas extensible.

Source: Directives de conception-cadre, deuxième édition, page 251:

Liste est optimisé pour la performance et la puissance au coût de la propreté des API et de la flexibilité.


1 commentaires

Cela semble être le plus facile à mettre en œuvre ... Il suffit de changer la liste à la collection qui n'ajoute pas toutes les frais générales d'observaBecollection Bien que vous perdiez une petite performance par rapport à la liste . Néanmoins, c'est plus que suffisant pour que vous obteniez le vote. THX!



0
votes

Cependant, ce faisant, des ruptures peuvent être capables d'énumérer sur la collection interne puisqu'elle est à l'intérieur.

Ce n'est pas vrai en supposant que vous suivez la technique appropriée et implémentez iEnumerable et icollection

Mais j'utiliserais une collection observable au lieu de réinventer la roue.

Et bien sûr, vous pouvez utiliser Extensions réactives pour faire ce dont vous avez besoin.


1 commentaires

Je ne pense pas que vous ayez besoin d'une iCollection. Je pense que iEnumerable suffit. Cela dit, il ressemble à la réponse de @anthony Pegramram est celui qui gère cette affaire ... juste déléguer à la collection interne. Cependant, il suffit de changer la classe de base de la liste à la collection semble faire le tour de sorte que c'est celui que je marque.



2
votes

ma pensée est à au lieu de la sous-classe Liste à la place pour créer juste une classe droite qui utilise un Liste en interne, puis je peut simplement exposer mon propre ajout / supprimer méthodes et gérer les ajustements à «Parent» là-bas. Cependant, ce faisant pauses à pouvoir énumérer sur la collection interne depuis qu'il est à l'intérieur.

Vous pouvez toujours implémenter iEnumerable sur votre collection personnalisée. Utilisez la liste <> en tant que détail de la mise en œuvre interne de la classe, et vous pouvez autoriser l'énumération via l'interface. xxx


3 commentaires

Mieux pourrait être de mettre en œuvre ilist , qui inclut iEnumerable , mais lui permet également d'être utilisé dans des contextes pouvant vouloir une liste ou à tout le moins, une collection.


@siride, bien sûr, il peut implémenter le iList Beefier . Il vient avec des fonctionnalités supplémentaires qu'il peut ou non vouloir fournir. Le point n'était pas spécifiquement quelle interface il a dû mettre en œuvre. En vérité, Il n'a pas à mettre en œuvre l'interface du tout (il peut simplement définir une méthode getenumerator approprié), il est tout simplement plus idiomatique à le faire.


@Antthony, vous permettant simplement de vous faire savoir que j'étais sur le point de marquer cela comme la réponse, mais cela ressemble à la chose plus simple à faire avec toujours à satisfaire tous nos besoins est juste de le changer de la liste à la collection qui permet moi remplacer ce que je dois. Néanmoins, vraiment cool de savoir que je peux juste déléguer le code d'énumération à la collection interne, donc j'ai voté le vôtre. Je vais devoir penser si ilist vs ienumerable est meilleur ... ilist peut être trop sûr pour nous puisque nous ne sommes vraiment intéressés que par les énumérations pour la plupart, mais être en mesure d'utiliser Il est utilisé que la liste est cool.



0
votes

Vous pouvez utiliser modèle d'observateur


1 commentaires

C'est un peu surkill pour simplement exposer l'interface iEnumerable d'une collection interne. Si je suis allé avec la sous-classe pure, le graphique d'objet ne s'aligne pas. Ne ressemble pas à ce que c'est le modèle approprié pour ce cas d'utilisation.



1
votes

10 commentaires

Voir mes commentaires concernant Observablecollection dans la réponse de CANGEN ci-dessus.


@Marque: Vous réalisez que vous réalisez qu'il existe un événement dédié aux articles ajoutés et que la collection ne détecte pas les modifications (les éléments eux-mêmes et uniquement des types qui implémentent inotifypropertychangned). Donc, je pense que ce surpeuplement supplémentaire que vous êtes inquiet ne existe pas réellement. L'appel de délégué et de la fonction virtuelle sont presque exactement le même coût.


En fait, lorsque vous remplacez la collection dans une sous-classe (liste ne prend pas en charge la mise en œuvre de l'ajout / Suppression de la mise en œuvre), vous interceptez le message appel lui-même pour que la collection de base ne connaisse pas encore l'appel était fait pour soulever de telles notifications. De plus, la collection n'a pas d'événements à élever! C'est ce que Observablecollection est pour. Et non, les objets eux-mêmes ne savent pas que les collections sont seules, qu'ils soient en eux ou non, je dois donc être en désaccord avec respect avec votre évaluation. Simplement la collection de sous-classement me donne ce que je suis après.


@Marque: Pourriez-vous garder vos commentaires sur le sujet? Ma réponse à propos de BindingList , qui a un événement. Et Le BindingList indique clairement que le < Code> Listchanged Événement est généré pour les modifications de l'élément uniquement lorsque inotifyPropertychanged interface est implémenté par le type d'objet contenu . Principalement, vous êtes confus sur les frais généraux des événements, cependant. Un design axé sur l'événement tel que BindingList est également rapide comme un appel de méthode virtuelle.


Je crois que je suis sur le sujet. J'ai précisément dit que votre suggestion ajoute beaucoup plus que nécessaire et que vous avez répondu à discuter de notifications et d'ilistpropertychangned des objets enfants. De plus, il contenait des informations incorrectes. Votre commentaire "... la collection ne détecte pas les modifications (les articles eux-mêmes et uniquement des types qui implémentent inotifyPropertychanged)." est en fait en arrière. BindingList écoute les changements de ses enfants s'ils soutiennent InotifyProperTychanged, pas l'inverse. Ne pas essayer d'être un troll. Les TOS du site disent spécifiquement d'appeler des informations incorrectes.


Un autre commentaire Re: Toi "L'appel de la délégation et l'appel de la fonction virtuelle sont presque exactement le même coût". Je pense que ça manque le point. Même si la liaison ne fait rien avec les notifications, il est toujours notifié de chaque modification des propriétés de ses éléments contenus, dont aucune collecte n'a besoin de connaître. Donc, ce n'est pas délégué-vs-virtuel, c'est plus un appel, même si vide, vs aucun appel du tout. Et encore une fois, si elle écoute inotifypropertychanged de ses enfants, cela peut être un lot d'appels, surtout si cette collection devient grande.


@MARQUEIV: Est-ce que emplacement implémente inotifypropertychanged ? Sinon, il n'y a pas d'appels aux changements au sein des enfants. N'oubliez pas que l'écoute n'est pas une action, élever un événement est l'action. Les enfants qui suivent les changements de propriété soulèvent un événement, lequel BindingList passe. Les enfants qui ne traitent pas les modifications de propriété ne provoquent aucune action, et le BindingList n'est pas non plus. En ce qui concerne votre réclamation "Les objets ne connaissent pas les collections", ils font en réalité, la collection utilise les événements de l'interface inotifypropertychanged pour indiquer à l'objet de lui-même.


Et lorsque le type ne met pas en œuvre inotifypropertychanged , rien ne se passe. Pour votre cas particulier, collection est un bon choix car vous devez ajouter de nouveaux membres au type de toute façon. Si vous n'avez pas besoin de nouveaux membres, BindingList vous permettrait de traiter des éléments ajoutés et supprimés, sans avoir à mettre en œuvre une nouvelle sous-classe.


Non, l'emplacement n'est pas. Bon point là-bas. C'est purement des données. Mais si cela le faisait, ce serait quelque chose d'extra adopté par rapport à la liaison à laquelle nous n'avons pas besoin. Encore une fois, la seule chose dont nous avons besoin est que la collection de savoir que quelque chose a été inséré ou retiré de lui-même, qu'une sous-classe de collection fait. Je suis toujours en désaccord que les articles ont toutes les connaissances sur leurs collections contenant en dehors d'un auditeur aux événements inotifypropertychanged de l'article, mais a) ce n'est pas le cas ici, et b) qui n'a rien à voir avec les collections, mais plutôt modifier la notification .


@MarqueIv: correct, et c'est tout ce que les articles enfants doivent générer les notifications de changement sont l'auditeur.