Laden...

Eine Liste von Interfaces als Parameter.. geht nicht

Erstellt von blubbla vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.450 Views
B
blubbla Themenstarter:in
8 Beiträge seit 2009
vor 14 Jahren
Eine Liste von Interfaces als Parameter.. geht nicht

Moin,

ich hab ein Interface:


    public interface IImageComboItem {
      ...
    }

und eine Klasse die dieses Interface implementiert


    class TaskState : IImageComboItem {
      ...
    }

sowie einen Singleton der die Liste ausgibt:


    class TaskStates {
      public List<TaskState> States { get; private set; }
      ...
    }

Nun habe ich eine Funktion die eine Liste solcher Interfaces erwartet:


    private void InitializeImageComboX(List<IImageComboItem> imgItems) {
      ...
    }

und rufe sie auf:


InitializeImageComboX(TaskStates.GetInstance().States);

Das geht leider nicht: "Die beste Übereinstimmung für die ünerladene ...-Methode hat einige ungültige Argumente"

Warum das?

Ich kann auch nicht casten:


InitializeImageComboX((List<IImageComboItem>)TaskStates.GetInstance().States);

Dann kommt

Eine Konvertierung ... ist nicht möglich.

Hat jemand eine Idee?

946 Beiträge seit 2008
vor 14 Jahren

Hat jemand eine Idee?

.NET 4 verwenden 😁 Da geht das ohne Probleme und auch noch performant.

Aktuell musst musst du trotzdem casten. So etwas wie

InitializeImageComboX(TaskStates.GetInstance().States.ConvertAll<IImageComboItem>(p => p));

müsste gehen.

mfg
SeeQuark

5.941 Beiträge seit 2005
vor 14 Jahren

Hallo zusammen

Stichwort Co- und Contravarianz.
Derzeit ist nur die Möglichkeit des Castens jedes einezelnen Elements einer Menge möglich.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

B
blubbla Themenstarter:in
8 Beiträge seit 2009
vor 14 Jahren

@SeeQuark

Wow, vielen Dank für die schnelle Hilfe. Ich bin neu bei C# und hätte jetzt manuell mit eigener Methode konvertiert - so ein Konstrukt (p => p) hab ich noch nie gesehen.

Danke danke danke!

946 Beiträge seit 2008
vor 14 Jahren

Das Konstrukt ist ein Lambda Ausdruck.
Falls es dich interessiert: [Artikel] Delegaten, anonyme Methoden, Lambda-Ausdrücke & Co.

Eigentlich ist es nicht einmal nötig. Mit .NET 3.5 geht auch

InitializeImageComboX(TaskStates.GetInstance().States.Cast<IImageComboItem>());

So ist es fast noch schöner...

mfg
SeeQuark

5.941 Beiträge seit 2005
vor 14 Jahren

Salute

Wow, vielen Dank für die schnelle Hilfe. Ich bin neu bei C# und hätte jetzt manuell mit eigener Methode konvertiert - so ein Konstrukt (p => p) hab ich noch nie gesehen.

Na dann wirds Zeit und an der Quelle bist du 😃.
Der folgende Artikel ist sehr zu empfehlen!

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

B
blubbla Themenstarter:in
8 Beiträge seit 2009
vor 14 Jahren

Eigentlich ist es nicht einmal nötig. Mit .NET 3.5 geht auch

InitializeImageComboX(TaskStates.GetInstance().States.Cast<IImageComboItem>());  

So ist es fast noch schöner...

Ja, fast schöner,

aber

Nein, geht so nicht. Vielleicht würde Cast<List<IImageComboBoxItems>> gehen?? Keine Ahnung, nicht probiert - weil da ist der Lambda-Ausdruck schon wieder schöner.

5.941 Beiträge seit 2005
vor 14 Jahren

Salute blubbla

Geht doch wunderbar:


  class Program
  {
    static void Main(string[] args)
    {
      var items = Enumerable.Repeat(new Item {Name = "Arbeit"}, 10);

      DumpItems(items.Cast<IItem>());

      Console.Read();
    }

    static void DumpItems(IEnumerable<IItem> items)
    {
      foreach(IItem item in items)
      {
        Console.WriteLine(item.Name);
      }
    }
  }

  public interface IItem
  {
    string Name { get; set; }
  }

  public class Item : IItem
  {
    public string Name
    {
      get;
      set;
    }
  }

Wie hast du es denn gemacht?

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

B
blubbla Themenstarter:in
8 Beiträge seit 2009
vor 14 Jahren

vielleicht ist das Problem, dass mein States kein Cast anbietet?

946 Beiträge seit 2008
vor 14 Jahren

Ich kann auch nicht casten:

InitializeImageComboX((List<IImageComboItem>)TaskStates.GetInstance().States);  

Und ein IEnumerable<T> ist halt keine List<T> 😉
Da ConvertAll<T> imho die einzige Methode ist, die eine List<T> zurückgibt wird es wohl die einzige Möglichkeit bleiben, solange der Parameter eine List<T> bleibt.
Aber das Problem an sich ist ja momentan ausreichend gut gelöst, so dass man es damit eigentlich beruhen lassen kann.

vielleicht ist das Problem, dass mein States kein Cast anbietet?

Cast ist eine Erweiterungsmethode. Mit using System.Linq; müsste sie eigentlich angeboten werden.
Aber du hast dann halt immer noch keine List<T>.

mfg
SeeQuark

5.941 Beiträge seit 2005
vor 14 Jahren

Hallo zusammen

Die erste Frage wäre eigentlich, wieso überhaupt List<T> als Eingangstyp?
Davon abgesehen kannst du auch ein IEnumerable<T>.ToList() machen, oder new List<T>(enumerableData<T>);.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

B
blubbla Themenstarter:in
8 Beiträge seit 2009
vor 14 Jahren

Die erste Frage wäre eigentlich, wieso überhaupt List<T> als Eingangstyp?

Weil ich C#-Newbie bin?

Aber wie dein Vorredner schon sagt: Die Frage ist eigentlich ausreichend beantwortet, funktioniert bei mir und ist alles was ich will.

Wenn es aus erfahrener Entwicklersicht dringende Gründe gibt, kein List zu nehmen, dann darfst du das aber gerne kurz erklären - ich lese es auf jeden Fall nochmal durch. Und ändere meinen Code dann vielleicht auch.

5.941 Beiträge seit 2005
vor 14 Jahren

Hallo blubbla

Dann wäre die Antwort: Du weisst es nicht, das hat nicht umbedingt was mit Newbie oder nicht Newbie zu tun.

Ich will in nächster Zeit mal was dazu in meinem Blog ausführlich schreiben, aber kurz:

Es gibt verschiedene Klassen und Interfaces für Mengen / Listen.
Wenn du nur eine einfache Auflistung brauchst, deine Menge / Liste also nur durchlaufen willst, keinen Index brauchst und auch nichts löschen / hinzufügen möchtest reicht IEnumerable bzw. das typisierte IEnumerable<T>.

Dann gibts noch ICollection / ICollection<T> mit ein wenig mehr Optionen (native Count Unterstützung) und dann das volle Paket mit IList / IList<T> das von einigen Klassen implementiert wird.

Du solltest immer nur so was kleines verwenden, was du auch wirklich benötigst und wenn möglich natürlich auf Interfaces bestehen, wann immer möglich.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

B
blubbla Themenstarter:in
8 Beiträge seit 2009
vor 14 Jahren

danke. Ja, dann schau ich öfters mal rein und versuch den Artikel zu finden. Den anderen den ihr mir oben gelinkt hab fand ich sehr hilfreich. Danke dafür.

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo zusammen,

ich habe nicht alles gelesen, aber ich denke, [Lösung] Problem bei Entkoppelung durch Interface passt auf das Problem und beschreibt die Zusammenhänge klarer.

herbivore

849 Beiträge seit 2006
vor 14 Jahren

Hi blubbla,

du kannst cast aufrufen wenn du den Namespace System.Linq einbindest. Der aufruf ist dann halt etwas anders:



using System.Linq;
.
.
.
TaskStates.GetInstance().States.Cast<IImageComboItem>();


49.485 Beiträge seit 2005
vor 14 Jahren

Hallo unconnected,

allerdings wird durch einen Cast eine neue, unabhängige Liste erstellt. Wenn man ReadOnlyBaseList <TBase, TDerived> - Ein hilfreicher Wrapper verwendet, wird nur ein Wrapper um die ursprüngliche Liste erstellt.

herbivore