| |
VB.NET - FortgeschritteneRe: Generischen Typen umwandeln | | | Autor: IIIIIChrisIIIII | Datum: 01.09.11 09:02 |
| Hallo!
Man könnte aber beispielsweise die Set-Methoden (zum Ändern der Properties) in der Klasse implementieren (da dort die Kovarianz nicht gilt), nicht jedoch im Interface vorgeben.
Genau so habe ich es jetzt gemacht und es ist perfekt! Zuerst dachte ich, dass es in meinem Fall so nicht ginge, weil ich die Property O setzten müsste. Dem ist aber nicht so. Denn wenn ich über die Schnittstelle zugreife, weiß ich ja nicht, von welchem Typ TA ist. Ergo könnte ich diesen Wert eh nicht setzten. Innerhalb meiner Implementierung habe ich dann konkrete Set-Methoden für die Properties, die einen Parameter vom Typ TA erwarten. Somit ist alles "schön" und ich muss auch nicht innerhalb der Implementierung hin und her casten.
Vielen Dank noch einmal für deine Hilfe! Hat mir SEHR weitergeholfen !
Beitrag wurde zuletzt am 01.09.11 um 09:03:34 editiert. | |
Generischen Typen umwandeln | | | Autor: IIIIIChrisIIIII | Datum: 31.08.11 16:23 |
| Hallo,
ich habe mal wieder ein ausgefallenes Problem. Hier erstmal der Code:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles Button1.Click
Dim O As Object = New Test(Of X, Button)
Dim T As ITest(Of Object, Windows.Forms.Control) = DirectCast(O, ITest(Of _
Object, Windows.Forms.Control))
End Sub
End Class
Public Interface ITest(Of TA, TB As Windows.Forms.Control)
End Interface
Public Class Test(Of TA, TB As Windows.Forms.Control)
Implements ITest(Of TA, TB)
End Class
Public Class X
End Class Wenn ich den Button klicke, erhalte ich in der zweiten Zeile des EventHandlers Button1_Click folgende Fehlermeldung:
Das Objekt des Typs "WindowsApplication1.Test`2[WindowsApplication1.X,System.Windows.Forms.Button]" kann nicht in Typ "WindowsApplication1.ITest`2[System.Object,System.Windows.Forms.Control]" umgewandelt werden.
Wahrscheinlich castet er nicht tief weswegen es zum obigen Fehler kommt. Kennt jemand eine Möglichkeit das doch zu umgehen?
Vielen Dank,
Chris | |
Re: Generischen Typen umwandeln | | | Autor: Preisser | Datum: 31.08.11 18:47 |
| Hallo,
Generika in Klassen sind standardmäßig weder ko- noch kontravariant, da sonst beispielsweise soetwas möglich wäre:
Option Strict On
Public Class Test(Of T)
Public Param As T
End Class
'' irgendwo im Code:
Public Sub Testen()
Dim a As Test(Of Bitmap) = New Test(Of Bitmap)()
Dim b As Test(Of Object) = a
b.Param = "Hi" 'String ist ein Untertyp von Object
Dim bmp As Bitmap = a.Param 'a.Param ist vom Typ Bitmap
End Sub Allerdings kann man bei Interfaces festlegen, dass Typparameter ko- oder kontravariant sein sollen (siehe hier), durch Angabe von "Of Out T" (Kovarianz) oder "Of In T" (Kontravarianz). Allerdings darf die Verwendung der Typparameter in Methoden der Klasse diese Einschränkung dann nicht verletzen.
Beitrag wurde zuletzt am 31.08.11 um 19:08:01 editiert. | |
Re: Generischen Typen umwandeln | | | Autor: IIIIIChrisIIIII | Datum: 31.08.11 19:12 |
| Hallo Preisser,
vielen Dank für deine Antwort! Das mit den ko oder kontravarianten Typenparametern ist mir nach meinem Post auch eingefallen, kommt aber in meinem konkreten Fall nicht vor. Ich hatte bei meinem Code der Einfachheitshalber einige Sachen rausgelassen/vergessen. So ist es vollständig:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles Button1.Click
Dim Obj As Object = New ExtTest()
Dim T As ITest(Of Object, Control) = DirectCast(Obj, ITest(Of Object, _
Control))
End Sub
End Class
#Region "Test1"
Public Interface ITest(Of TA, TB As Windows.Forms.Control)
Property O As TA
Property Ctrl As TB
End Interface
Public Class Test(Of TA, TB As Windows.Forms.Control)
Implements ITest(Of TA, TB)
Public Property Ctrl As TB Implements ITest(Of TA, TB).Ctrl
Get
End Get
Set(ByVal value As TB)
End Set
End Property
Public Property O As TA Implements ITest(Of TA, TB).O
Get
End Get
Set(ByVal value As TA)
End Set
End Property
End Class
Public Class ExtTest
Inherits Test(Of X, Button)
End Class
Public Class X
End Class
#End Region Dadurch wird klar, dass ich weder ko noch kontravarianz verwenden kann.
Ich verstehe zwar den Grund, wieso der compiler Meckert - dein Beispiel ist einleuchtend. Aber leider kann ich dadurch kein Generics mehr verwenden.
Vielleicht etwas zum Hintergrund: Ich habe ein Programm, dass über Reflection alle Implementierungen der besagten Schnittstelle instanziert. Die Typenparameter für die Schnittstelle sind einmal der Typ für ein Settings-Objekt und der zweite für die GUI (also Control).
Erstelle ich ein Projekt mit einer neue Klasse, die diese Schnittstelle implmeneitiert kann ich innerhalb der Klasse direkt auf die Settings und die GUI (die sich logischerweise auch spezifisch im gleichen Projekt befinden) zugreifen (also über die Properties).
Von außen dachte ich könnte ich immer auf Object / Control zugreifen.
Nun muss ich die Generics entfernen und die Properties Settings und GUI der Schnittstelle auf Object und Control ändern, wodurch beim Implementieren einer solchen Schnittstelle ich intern immer casten muss. Die Generic-Variante fand ich "schöner" ;).
Für andere Tipps bin ich sehr dankbar.
Vielen Dank noch einmal!
Chris
Beitrag wurde zuletzt am 31.08.11 um 19:15:32 editiert. | |
Re: Generischen Typen umwandeln | | | Autor: Preisser | Datum: 31.08.11 21:38 |
| Hallo,
wenn sich die beiden Properties der Klasse/Interface später nicht mehr verändern (readonly), könntest du Kovarianz verwenden, sodass man über eine weniger spezifische Typvariable darauf zugreifen kann.
Dann müssten die Parameter allerdings schon im Konstruktur der Klasse übergeben werden.
z.B.
Public Interface ITest(Of Out TA, Out TB As Windows.Forms.Control)
ReadOnly Property O As TA
ReadOnly Property Ctrl As TB
End Interface
Public Class Test(Of TA, TB As Windows.Forms.Control)
Implements ITest(Of TA, TB)
Private ReadOnly _Ctrl As TB
Private ReadOnly _O As TA
Public Sub New(O As TA, Ctrl As TB)
Me._O = O
Me._Ctrl = Ctrl
End Sub
Public ReadOnly Property Ctrl As TB Implements ITest(Of TA, TB).Ctrl
Get
Return _Ctrl
End Get
End Property
Public ReadOnly Property O As TA Implements ITest(Of TA, TB).O
Get
Return _O
End Get
End Property
End Class Dann könnte man sowas schreiben, ohne dass der Compiler meckert:
Dim i1 As ITest(Of String, TextBox) = New Test(Of String, TextBox)( _
"Test", New TextBox())
Dim i2 As ITest(Of Object, Control) = i1 Wenn sich die Properties allerdings ändern können sollen, geht dies nicht so direkt (zumindest für den selben Typparameter), da (soweit ich weiß) bei Parametern, die einer Methode übergeben werden, nur Kontravarianz verwendet werden kann, jedoch beim Rückgabewert nur Kovarianz.
Man könnte aber beispielsweise die Set-Methoden (zum Ändern der Properties) in der Klasse implementieren (da dort die Kovarianz nicht gilt), nicht jedoch im Interface vorgeben.
Beitrag wurde zuletzt am 31.08.11 um 22:15:27 editiert. | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
vb@rchiv CD Vol.6 vb@rchiv Vol.6
Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
Online-Update-Funktion Entwickler-Vollversionen u.v.m.Jetzt zugreifen Tipp des Monats TOP! Unser Nr. 1
Neu! sevDataGrid 3.0
Mehrspaltige Listen, mit oder ohne DB-Anbindung. Autom. Sortierung, Editieren von Spalteninhalten oder das interaktive Hinzufügen von Datenzeilen sind ebenso möglich wie das Erstellen eines Web-Reports. Weitere Infos
|