2009-05-19 4 views
6

Ich arbeite in VB.net und habe eine Klasse, Foo, die eine Schnittstelle implementiert, IBar. Ich habe eine Liste von Foo's, aber ich muss eine Liste von IBar's in einer Funktion übergeben, aber ich bekomme Casting Fehler, auch wenn ich DirectCast benutze. Mein Code istWie kann ich eine Liste eines Objekts in eine Liste einer Schnittstelle umwandeln, die das Objekt in VB.net implementiert?

Class Foo 
    Implements IBar 
End Class 

Interface IBar 
End Interface 

Sub DoIt(ByVal l As List(Of IBar)) 
End Sub 

Sub Main() 
    Dim FooList As New List(Of Foo) 
    DoIt(FooList) 
End Sub 

Sub Main2() 
    Dim FooList As New List(Of Foo) 
    DoIt(DirectCast(FooList, List(Of IBar))) 
End Sub 

Sub MainWorks() 
    Dim FooList As New List(Of Foo) 
    Dim IBarList As New List(Of IBar) 

    For Each f As Foo In FooList 
     IBarList.Add(f) 
    Next 

    DoIt(DirectCast(IBarList, List(Of IBar))) 
    DoIt(IBarList) 
End Sub 

in den beiden Haupt und Main2 ich

Value of type 'System.Collections.Generic.List(Of FreezePod.Pod.Foo)' cannot be converted to 'System.Collections.Generic.List(Of FreezePod.Pod.IBar)'. 

Mainworks arbeitet, aber es wäre wirklich ärgerlich und ineffizient sein überall zu tun zu haben, dass ich will, diese Funktion aufzurufen.

Antwort

2

Hinzufügen dieser Lösung als eine andere Antwort, sollte dies tun, was Sie wollen.

Sub DoIt(Of T As IBar)(ByVal l As List(Of T)) 
End Sub 

Definieren der Untergruppe mit Generics.

4

Duplicate question aber für C# (gleiches Problem). Dort gibt es verschiedene Antworten, die Sie in VB übersetzen können. Der Grund, warum Sie nicht können, ist covariance and contravariance.

Ich bin kein VB-Typ, aber meine bevorzugte C# -Weise ist System.Collections.Generic.List<T>.ConvertAll<Tout>(x => (Tout)x) anrufen. (Ich weiß nicht, wie das übersetzt, wenn es tut, zu VB.)

VB Übersetzung:

System.Collections.Generic.List(Of T).ConvertAll(Of TOut)(Function(x) CType(x, TOut))

5

Das Problem ist, dass generische Typen wie List (Of T) nicht konvertieren zu einer anderen Liste (Of U), selbst wenn die Besetzung garantiert sicher ist. Hilfe kommt dafür in VS2010, die Ihnen jetzt natürlich nicht wirklich hilft.

wie ich glaube, auch in den zu verlinkten Thread vorgeschlagen wurde, wenn DoIt eine IEnumerable von IBar nehmen kann statt einer Liste, könnten Sie tun:

DoIt(FooList.Cast(Of IBar)) 

oder wenn Sie wirklich eine Liste benötigt (und konnte nehmen Sie den Overhead), könnten Sie eine Liste erhalten:

DoIt(FooList.Cast(Of IBar).ToList) 
1

ist eine abgeleitete Basisklasse keine Option, und haben die Basisklasse die Schnittstelle implementieren. Das würde es funktionieren lassen.

Class BaseFoo 
    Implements IBar 
End Class 

Class Foo 
    Inherits BaseFoo 
End Class 

Sub DoIt(ByVal l As List(Of BaseFoo)) 
End Sub 

So ähnlich.

+0

In diesem Fall wäre das nicht angemessen. Die Implementierer von IBar haben bereits verschiedene Basisklassen, die völlig unabhängig sind von dem, was die Schnittstelle tut. Ich behalte das im Hinterkopf, wenn das wieder auftaucht. – thefroatgt

+0

Ich aktualisiert mit einem Generika-Ansatz in der Sub, könnten Sie sich ansehen. – AnotherDan

+0

Ich habe den Generics-Ansatz getestet - es scheint reibungslos zu funktionieren. – AnotherDan

Verwandte Themen