Suggestions voulais avec des Listes ou des agents Recenseurs de T lorsque l'héritage de classes génériques

StackOverflow https://stackoverflow.com/questions/53395

  •  09-06-2019
  •  | 
  •  

Question

Je sais que la réponse ne va pas être simple, et je l'ai déjà utiliser un couple de (je pense que laid) cludges.Je suis simplement à la recherche d'une certaine élégance réponses.

Classe abstraite:

public interface IOtherObjects;

public abstract class MyObjects<T> where T : IOtherObjects
{
   ...

   public List<T> ToList()
   {
       ...
   }
}

Enfants:

public class MyObjectsA : MyObjects<OtherObjectA> //(where OtherObjectA implements IOtherObjects)
{


}

public class MyObjectsB : MyObjects<OtherObjectB> //(where OtherObjectB implements IOtherObjects)
{


}

Est-il possible, en boucle à travers une collection de MyObjects (ou d'autres analogues de groupement, générique ou autre) pour ensuite les utiliser à ToList la méthode de la MyObjects classe de base, que nous n'avons pas spécialement de connaître le type de T à ce point.

MODIFIER Pour des exemples précis, chaque fois que cela est venu, j'ai pensé pendant un moment, et fait quelque chose de différent au lieu de cela, donc il n'y a pas d'exigence actuelle.mais comme c'est venu assez souvent, j'ai pensé que je pourrais flotter.

MODIFIER @Sara, ce n'est pas le type spécifique de la collection, je me soucie de, il pourrait être une Liste, mais tout le ToList méthode de chaque instance est relativement inutilisable, sans un type anonyme)

@aku, le vrai, et cette question peut être relativement hypothétique, cependant, être en mesure de récupérer, et de travailler avec une liste de T des objets, sachant que leur type de base serait très utile.Avoir la ToList retour d'une Liste De BaseType a été l'une de mes solutions de contournement

MODIFIER @ tous:Jusqu'à présent, cela a été le genre de discussion que j'espérais, mais il confirme largement tout ce que je soupçonne.Merci à tous, mais une personne d'autre, n'hésitez pas à l'entrée.

MODIFIER@Rob, Oui, il fonctionne pour un type défini, mais pas quand le type est connu sous le nom d'une Liste de IOtherObjects.

@Rob De nouveau Merci.Qui a généralement été mon cludgy solution de contournement (pas de manque de respect :) ).Soit ça, ou à l'aide de la ConvertAll fonction Abattu par un délégué.Merci de prendre le temps de comprendre le problème.

QUALIFICATION MODIFIER dans le cas où j'ai été un peu déroutant

Pour être plus précis, (j'ai peut-être laisser ma dernière mise en œuvre de ce trop complexe):

disons que j'ai 2 types d'objet, B et C héritent de l'objet A.

De nombreux scénarios ont présenté eux-mêmes où, à partir d'une Liste de B ou une Liste de C, ou dans d'autres cas, une Liste d' - mais je ne sais pas lequel, si je suis dans une classe de base, j'ai besoin d'un moins Liste spécifique d'A.

L'exemple ci-dessus était une édulcorée exemple de l' Liste Des Moins Spécifiques problème de l'incarnation la plus récente.

Habituellement, il a présenté lui-même, comme je pense, par le biais de scénarios possibles qui limite la quantité de code qui a besoin de l'écriture et semble un peu plus élégant que les autres options.Je voulais vraiment une discussion de possibilités et d'autres points de vue, que j'ai plus ou moins eu.Je suis étonné que personne n'a mentionné ConvertAll() jusqu'à présent, c'est une autre solution de contournement que j'ai utilisé, mais un peu trop verbeux pour les scénarios à portée de main

@Rob Encore Une Fois et Sara

Merci, cependant je pense comprendre génériques dans tous leurs statique contexted gloire, et comprendre les questions en jeu ici.

La conception réelle de notre système et de l'utilisation des génériques (et je peux le dire, sans un soupçon de partialité, que je n'étais qu'un des acteurs de la conception), a été bien fait.C'est lorsque j'ai travaillé avec l'API de base, j'ai trouvé les situations, quand j'ai été dans le mauvais champ d'application pour faire quelque chose de tout simplement, à la place j'ai eu à traiter avec eux avec un peu moins élégant que j'aime (en essayant soit de faire de l'esprit ou peut-être paresseux, je vais accepter l'une de ces étiquettes).

Mon dégoût pour ce que j'ai appelé un cludge est en grande partie que nous avons besoin de faire une boucle à travers notre record de simplement convertir les objets à leur valeur de base, qui peut être un gain de performance.

Je suppose que je me demandais si quelqu'un d'autre a rencontré ce dans leur codage avant, et si quelqu'un avait été plus malin, ou, au moins, de plus élégant, de m'en occuper.

Était-ce utile?

La solution

Si vous avez

class B : A
class C : A

Et vous avez

List<B> listB;
List<C> listC;

que vous souhaitez traiter comme une Liste du type parent

Ensuite, vous devez utiliser

List<A> listA = listB.Cast<A>().Concat(listC.Cast<A>()).ToList()

Autres conseils

pourquoi pensez-vous avoir une collection de MyObjects?Est-il une raison spécifique que vous n'avez pas une Liste?

Dans votre cas MyObjectsA et MyObjectsB n'ont pas de commune prédécesseur.Classe générique est modèle pour différentes classes pas une classe de base commune.Si vous souhaitez avoir des propriétés communes dans les différentes classes d'utilisation des interfaces.Vous ne pouvez pas appeler ToList dans une boucle de la cause signature différente dans les différentes classes.Vous pouvez créer ToList qui renvoie les objets plutôt que de type spécifique.

Vous pouvez encore accéder à la ToList() la méthode, mais puisque vous n'êtes pas sûr du type, n'est ce pas ce travail?

foreach(var myObject in myObjectsList)
    foreach(var obj in myObject.ToList())
        //do something

Bien sûr, cela ne fonctionne que sur C# 3.0.

Notez que l'utilisation de la var est simplement de supprimer la condition de savoir de quel type de listes contiennent;contrairement à Frank commentaires que j'ai des délires que var fera le typage dynamique.

OK, je suis confus, le code suivant fonctionne très bien pour moi (la curiosité a obtenu le meilleur de moi-même!):

// Original Code Snipped for Brevity - See Edit History if Req'd

Ou ai-je raté quelque chose?

Mise à jour Suite à la Réponse de l'OP

OK, maintenant je suis vraiment confus..Ce que vous dites, c'est que vous voulez obtenir une Liste de Tapé les valeurs à partir d'un générique/abstract Liste?(l'enfant des classes donc devenue sans objet).

Vous ne pouvez pas retourner une Liste Tapée si les Types sont les enfants/interface réalisateurs - ils ne correspondent pas!Bien sûr, vous pouvez obtenir une Liste des éléments qui sont d'un type spécifique de l'abrégé de la Liste comme suit:

    public List<OfType> TypedList<OfType>() where OfType : IOtherObjects
    {
        List<OfType> rtn = new List<OfType>();

        foreach (IOtherObjects o in _objects)
        {
            Type objType = o.GetType();
            Type reqType = typeof(OfType);

            if (objType == reqType)
                rtn.Add((OfType)o);
        }

        return rtn;
    }

Si je suis encore ici pouvez-vous reformuler votre question?!(Il ne semble pas comme je suis le seul à pas sûr de ce que vous conduisez).Je suis en train d'établir s'il s'agit d'un malentendu de génériques sur votre partie.

Une Autre Mise À Jour :D

À droite, il semble que vous voulez/besoin de l'option pour obtenir la Liste tapée, ou la liste de base oui?

Ce serait faire de votre classe abstraite ressembler à ceci: vous pouvez utiliser ToList pour obtenir le type de béton, ou ToBaseList() pour obtenir une Liste du type d'interface.Cela devrait fonctionner dans tous les scénarios que vous avez.Cela vous aide?

public abstract class MyObjects<T> where T : IOtherObjects
{
    List<T> _objects = new List<T>();

    public List<T> ToList()
    {
        return _objects;
    }

    public List<IOtherObjects> ToBaseList()
    {
        List<IOtherObjects> rtn = new List<IOtherObjects>();
        foreach (IOtherObjects o in _objects)
        {
            rtn.Add(o);
        }
        return rtn;
    }
}

Mise à jour #3

Ce n'est pas vraiment un "cludgy" solution de contournement (pas de manque de respect prises) - c'est la seule façon de le faire..Je pense que le plus gros problème ici est une conception/grok problème.Vous avez dit que vous aviez un problème, ce code résout.Mais si vous vous attendiez à faire quelque chose comme:

public abstract class MyObjects<T> where T : IOtherObjects
{
    List<T> _objects = new List<T>();

    public List<IOtherObjects> Objects
    { get { return _objects; } }
}
#warning This won't compile, its for demo's sake.

Et être en mesure de choisir et choisir les types qui viennent d'en sortir, comment faire autrement pourrait vous le faire?!J'ai l'impression que vous ne comprenez pas vraiment ce qui est le point de génériques, et vous essayez de les amener à faire quelque chose qu'ils ne sont pas conçus pour ça!?

J'ai récemment découvert l'

List<A>.Cast<B>().ToList<B>()

de modèle.

C'est exactement ce que je cherchais,

Les génériques sont utilisés pour statique fois les vérifications de type pas exécution de l'expédition.Utiliser l'héritage/interfaces pour l'exécution d'expédition, l'utilisation de médicaments pour le type de compilation des garanties.

interface IMyObjects : IEnumerable<IOtherObjects> {}
abstract class MyObjects<T> : IMyObjects where T : IOtherObjects {}

IEnumerable<IMyObjects> objs = ...;
foreach (IMyObjects mo in objs) {
    foreach (IOtherObjects oo in mo) {
        Console.WriteLine(oo);
    }
}

(Évidemment, je préfère Enumerables sur les Listes.)

OU Juste utiliser un langage dynamique comme VB.:-)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top