2017-03-08 2 views
1

Versuchen, einem Freund hier draußen zu helfen. Ich bin kein Microsoft-Programmierer.Erstellen eines Arrays, einer Liste oder einer Sammlung von untergeordneten Elementen einer abstrakten Basisklasse

public abstract class Foo {} 
public class Bar : Foo {} 
public class Baz : Foo {} 

Das scheint ziemlich gut, dann in einer anderen Klasse zu arbeiten, er Anordnungen von Bar instanziieren und Baz wie diese

public class MyClass { 
    Bar[] Bars = new Bar[] { new Bar[] { new Bar(), new Bar() } } 
    Baz[] Bazs = new Baz[] { new Baz[] { new Baz(), new Baz() } } 
} 

die Frage, ob er will einen Accessor haben, die Foos und Bars zurück wie macht er das?

public class MyClass { 
    Bar[] Bars = new Bar[] { new Bar[] { new Bar(), new Bar() } } 
    Baz[] Bazs = new Baz[] { new Baz[] { new Baz(), new Baz() } } 
    public IEnumerable<Foo> GetFoos() { 
    // No go. 
    return [ Bars, Bazs ]; 

    // Also No go. 
    List<Foo> test = new List<Foo> { Bars, Bazs }; 
    return test; 
    } 
} 

Ich denke, dass Microsoft dies normalerweise mit Schnittstellen implementiert, aber seine Zuweisung fordert die Verwendung von abstrakten Basisklassen. Gibt es eine Möglichkeit, eine Liste oder ein Array von Kindern einer abstrakten Basisklasse zurückzugeben?

+0

In beiden Szenarien können Sie Erstelle keine Instanz von 'new Foo()', da 'Foo' eine abstrakte Klasse ist. Sie können Objekte von Bar und Baz erstellen und ein Array von Foo zurückgeben. Sehen Sie, ob die folgende Antwort hilft. –

+0

Es scheint ein Syntaxfehler in Ihrem Code zu sein: Um ein Array zu erstellen, benutzen Sie 'Bar [] Bars = new Bar [] {new Bar(), new Bar()}' Sie scheinen eine Art verschachteltes Array mit '' zu erstellen new Bar [] {new Bar [] {... ' – HugoRune

Antwort

0

In beiden Szenarien können Sie keine Instanz von 'new Foo()' erstellen, da 'Foo' eine abstrakte Klasse ist. Sie können Objekte von Bar und Baz erstellen und ein Array von Foo zurückgeben. Sehen Sie, ob die folgende Antwort hilft.

public class MyClass 
    { 
     Foo[] Foos1 = new Foo[] { new Bar(), new Bar() }; 
     Foo[] Foos2 = new Foo[] { new Baz(), new Baz() }; 

     // OR use as below 

     /* 
     Foo[] Foos1 = new Bar[] { new Bar(), new Bar() }; 
     Foo[] Foos2 = new Baz[] { new Baz(), new Baz() }; 
     */ 

     public IEnumerable<Foo> GetFoos1() 
     { 
      // Works. 
      return Foos1; 
     } 

     public IEnumerable<Foo> GetFoos2() 
     { 
      // Works 
      List<Foo> test = new List<Foo>(); 
      test.AddRange(Foos2); 
      return test; 
     } 
    } 
+0

Gibt es sowieso Foos1 und Foos2 stark an dieser Stelle des Codes getippt, und damit es trotzdem funktioniert? Oder habe ich sie dort in das ABC eingegeben? –

+0

Nicht sicher, ob ich das Problem klar verstanden habe. Wenn Sie das Problem/Szenario, das Sie lösen möchten, erklären können, ist das hilfreich. Sie können die ersten 2 Zeilen des obigen Problems auch in der aktualisierten Antwort ersetzen. –

+0

In diesem verlieren Sie die Tippinformationen vor dem Punkt, den Sie von der Funktion zurückgeben - wenn Sie das "Foo [] Foos1" deklarieren, wenn ich Foos1 vom Typ Bar [] deklarieren wollte, könnte ich das an diesem Punkt tun und dann später Cast oder etwas zu Foo? –

0

Um einen anderen IEnumerable'T zu einer Liste hinzuzufügen, müssen Sie „AddRange“ wie verwenden:

List<Foo> test = new List<Foo>(); 
test.AddRange(Foos); 
test.AddRange(Bars); 

return test; 

Sie auch die Liste Konstruktor Überlastung, um eine vorhandene IEnumerable hinzufügen können‘ T zu Ihrer Liste:

List<Foo> test = new List<Foo>(Foos); 
test.AddRange(Bars); 

return test; 
+0

unten funktioniert nicht, da Foo eine abstrakte Basisklasse ist und keinen Konstruktor hat. –

0

Es ist nicht notwendig, eine Kopie Ihrer Arrays zu erstellen. Der folgende Code wird eine IEnumerable<Foo> erzeugen, die immer den aktuellen Inhalt Ihrer Arrays reflektiert, und verbrauchen keine signifikante Menge an Speicher:

public class MyClass 
{ 
    private Bar[] Bars = new Bar[] {new Bar(), new Bar()}; 
    private Baz[] Bazs = new Baz[] {new Baz(), new Baz()}; 

    public IEnumerable<Foo> GetFoos() 
    { 
     // Cast Bars as an Enumerable<Foo>, then append Bazs 
     // (no need to explicitly cast Bazs) 
     return Bars.AsEnumerable<Foo>().Concat(Bazs); 

     // or 

     // Create an empty Enumerable<Foo>, then append Bazs and Bars 
     return Enumerable.Empty<Foo>().Concat(Bars).Concat(Bazs); 
    } 
} 

Das zurückgegebene Objekt von GetFoos() Hier ist nur ein Hinweis auf die beiden ursprünglichen Arrays. Wenn Code diesen IEnumerable auflistet, greift er implizit auf die beiden ursprünglichen Arrays zu. Wenn also nach dem Aufruf von GetFoos(), aber vor der Verwendung des Ergebnisformulars GetFoos(), jemand jedes Element von Bars durch NULL ersetzt, dann sieht der Code, der GetFoos() aufgerufen hat, nur eine Menge NULL.

Wenn Sie nicht über den Inhalt des zurück IEnumerable ändern möchten, wenn Sie den Inhalt der ursprünglichen Arrays zu ändern, müssen Sie eine Kopie erstellen, wie folgt aus:

public IEnumerable<Foo> GetFoos() 
{ 
    return Enumerable.Empty<Foo>().Concat(Bars.ToArray()).Concat(Bazs.ToArray()); 
} 
Verwandte Themen