Anregungen wollte mit Listen oder Enumeratoren von T, wenn Erben von generischen Klassen

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

  •  09-06-2019
  •  | 
  •  

Frage

Ich weiß, die Antwort ist nicht einfach, und ich bereits ein paar (ich denke, hässlich) cludges.Ich bin einfach auf der Suche nach etwas elegantem Antworten.

Abstrakte Klasse:

public interface IOtherObjects;

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

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

Kinder:

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


}

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


}

Ist es möglich, die Schleife durch eine Sammlung von MyObjects (oder ähnliche Gruppierung, generische oder anderweitig), um dann zu nutzen, um ToList Methode der MyObjects Basis-Klasse, da wir nicht konkret wissen, die Art der T an dieser Stelle.

BEARBEITEN Als konkrete Beispiele, Wann immer dies hat zu kommen, ich habe darüber nachgedacht für eine Weile, und etwas anderes gemacht statt, so gibt es keine Anforderung.aber als es kam bis jetzt Recht Häufig, ich dachte, ich würde schweben es.

BEARBEITEN @Sara, es ist nicht die bestimmte Art der Sammlung, die ich über Pflege, es könnte sein, eine Liste, aber immer noch die ToList-Methode für jede Instanz ist relativ unbrauchbar, ohne ein anonymer Typ)

@aku, wahr, und diese Frage kann relativ hypothetische, jedoch abrufen zu können, und arbeiten mit einer Liste von T der Objekte, zu wissen, nur Ihre Basis geben würde, sehr nützlich sein.Mit der ToList zurückgeben einer Liste Von BaseType war eines meiner Problemumgehungen

BEARBEITEN @ all:So weit, dies ist die Art von Diskussion, die ich erhofft hatte, obwohl es weitgehend bestätigt alles was ich vermutete.Vielen Dank an alle, so weit, sondern jemand anderes, fühlen sich frei, um Eingang.

BEARBEITEN@Rob, ja, es funktioniert für einen benutzerdefinierten Typ, aber nicht, wenn die Art ist nur bekannt, als eine Liste von IOtherObjects.

@Rob Wieder Vielen Dank.Das hat in der Regel meine cludgy Abhilfe (keine Respektlosigkeit :) ).Entweder das, oder über die ConvertAll-Funktion Niedergeschlagen durch ein delegieren.Danke für die Zeit nehmen, das problem zu verstehen.

QUALIFIKATION BEARBEITEN in Fall ich habe ein wenig verwirrend

Um genauer zu sein, (ich kann lassen Sie meine neueste Form dieses bekommen, es zu Komplex):

lets sagen, ich habe 2 Objekttypen, B und C Erben von Objekt A.

Viele Szenarien, die sich vorgestellt haben, wo, aus einer Liste B und Liste C, oder in anderen Fällen eine Liste mit entweder - aber ich weiß nicht, was wenn ich bin an einer Basis-Klasse, ich brauchte eine weniger spezifische Liste von A.

Das obige Beispiel war eine verwässerte Beispiel der Liste Der Weniger Spezifische problem die jüngste Inkarnation.

In der Regel es hat sich vorgestellt, wie ich glaube, durch eine mögliche Szenarien, beschränken Sie die Menge an code zu schreiben und scheint ein wenig eleganter ist als die anderen Optionen.Eigentlich wollte ich eine Diskussion von Möglichkeiten und andere Sichtweisen, die ich mehr oder weniger habe.Ich bin überrascht, dass niemand erwähnt hat ConvertAll() so weit, wie das ist eine andere Problemumgehung, die ich verwendet habe, aber ein wenig zu ausführlich für die Szenarien an die hand

@Rob Noch Einmal und Sara

Danke, aber ich habe das Gefühl, ich verstehe Generika in alle Ihre statischen contexted Herrlichkeit, und Verstand es, die Probleme, die hier im Spiel.

Das tatsächliche design des Systems und die Verwendung von Generika-ist es (und dies kann ich sagen, ohne nur einen Hauch von Befangenheit, wie ich, war nur einer der Spieler im design), gut gemacht.Es ist, wenn ich haben mit der Kern-API, die ich gefunden habe, Situationen, wenn ich in den falschen Bereich für etwas einfach stattdessen hatte ich mit Ihnen zu tun mit etwas weniger elegant als ich es gerne (versuchen entweder zu schlau oder vielleicht auch faul - ich nehme an, dieser labels).

Meine Abneigung gegen das, was ich als cludge ist weitgehend, die wir benötigen, zu tun, eine Schleife über unseren Datensatz einfach zu konvertieren, die Objekte, um Ihre Basis-Wert kann auch ein performance-hit.

Ich glaube, ich war Frage mich, ob jemand anderes hatte, kommen die über diese in Ihrer Codierung vor, und wenn jemand hatte, der war klüger, oder zumindest eleganter, als mir im Umgang mit ihm.

War es hilfreich?

Lösung

Wenn Sie haben

class B : A
class C : A

Und Sie haben

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

Sie behandeln wollen, wie Sie eine Liste der übergeordneten Typ

Dann sollten Sie

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

Andere Tipps

warum haben Sie eine Sammlung von MyObjects?Gibt es einen bestimmten Grund, warum Sie nicht haben eine Liste?

In Ihrem Fall MyObjectsA und MyObjectsB keinen gemeinsamen Vorgänger.Generische Klasse Vorlage für verschiedene Klassen, die nicht einer gemeinsamen Basisklasse.Wenn Sie wollen haben gemeinsame Eigenschaften in verschiedene Klassen, die Schnittstellen verwenden.Sie können Sie nicht anrufen ToList in einer Schleife verursachen, es hat verschiedene Signatur in verschiedene Klassen.Sie können erstellen ToList zurückgibt Objekte anstatt spezifische Typ.

Sie können wahrscheinlich immer noch Zugriff auf die ToList () - Methode, aber da Sie sich nicht sicher sind, die Art, das nicht funktioniert?

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

Natürlich funktioniert das nur auf C# 3.0.

Beachten Sie, dass die Verwendung von var wird lediglich die Anforderung entfernen möchten wissen, welcher Art die Listen enthalten;im Gegensatz zu Frank-Kommentare, dass ich Wahnvorstellungen, die var wird um die Eingabe dynamisch.

OK, ich bin verwirrt, der folgende code funktioniert gut für mich (Neugier erwischte den besseren von mir!):

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

Oder habe ich etwas verpasst?

Update-Folgende Reaktion aus der OP

OK jetzt bin ich wirklich verwirrt..Was Sie sagen, ist, dass Sie möchten, um eine Liste der Typisierte Werte, die von einem generischen/abstract-Liste?(die Kind-Klassen, daher irrelevant).

Sie können nicht Rückkehr eine Typisierte Liste, wenn die Typen sind Kinder/interface implementors - Sie passen nicht!Sie können natürlich eine Liste von Elementen, die eine bestimmte Art, die von der abstrakten Liste wie folgt:

    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;
    }

Wenn ich mich noch dran-Basis hier können Sie die bitte formulieren Sie Ihre Frage?!(Es scheint nicht, wie ich der einzige bin nicht sicher, was Sie fahren).Ich bin versucht, festzustellen, ob es gibt ein Missverständnis, Generika auf Ihrem Teil.

Noch Ein Update :D

Richtig, so sieht es aus wie Sie wollen/müssen die option, um die eingegebene Liste aus, oder die Basis-Liste ja?

Dies würde Ihre abstrakte Klasse wie folgt Aussehen: Sie verwenden können ToList zu bekommen, den konkreten Typ oder ToBaseList (), um eine Liste der interface-Typ).Diese Arbeit sollte in jedem Szenarien, die Sie haben.Hilft das?

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;
    }
}

Update #3

Es ist nicht wirklich ein "cludgy" Abhilfe (keine Respektlosigkeit genommen) - das ist der einzige Weg, es zu tun..Ich denke, das größere Problem hier ist ein design - /grok problem.Sie sagten, Sie hätten ein problem, dieser code löst.Aber wenn Sie erwartet hatten, etwas zu tun wie:

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.

Und in der Lage zu pick-und-wählen Sie die Typen, die kommen aus ihm heraus, wie sonst könnte Sie es tun?!Ich habe das Gefühl, Sie nicht wirklich verstehen, was der Punkt von Generika sind, und Sie versuchen, Sie zu bekommen, etwas zu tun Sie sind nicht ausgelegt!?

Ich habe vor kurzem fand die

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

Muster.

Es tut genau, was ich suchte,

Generika für statische Zeit-Typ-Prüfungen nicht runtime Versand.Verwenden Sie Vererbung/interfaces zur Laufzeit zu Versand, verwenden generics for compile-time type Garantien.

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);
    }
}

(Offensichtlich, ich bevorzuge Enumerables über Listen.)

ODER Nur mit einem richtigen dynamischer Sprachen wie VB.:-)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top