| |
VB.NET - Ein- und UmsteigerRe: Referenz auf Structure zurückgeben | | | Autor: keco | Datum: 17.01.10 18:28 |
| Eine Structure ist ein Werttyp und befindet sich auf dem Stack im Speicher. Ist sie ungültig, wird sie gelöscht. Bei jeder Übergabe an eine Methode wird, wie du bereits erwähnt hast, eine Kopie der Werte erzeugt. Anders ist das, wenn eine Structure einen Referenztypen enthält, dann kann sie auch auf dem Heap existieren. Referenztypen hingegen leben immer auf dem verwalteten Heap und werden nicht einfach gelöscht, wenn sie für ungültig erklärt werden. Erst durch den GC. Bei der Übergabe an andere Methoden wird dabei immer eine Referenz auf den Speicher übergeben. | |
Referenz auf Structure zurückgeben | | | Autor: Friedel84 | Datum: 17.01.10 17:33 |
| Hallo VB-Gemeinschaft,
also ich bin über ein Problem gestolpert. Um es zu veranschaulichen habe ich ein fiktives Beispiel geschrieben. Hier erstmal der Code:
Public Class Form1
Public Structure Pupil
Private myName As String
Private myId As Integer
Property ID() As Integer
Get
Return myId
End Get
Set(ByVal value As Integer)
myId = value
End Set
End Property
Property Name() As String
Get
Return myName
End Get
Set(ByVal value As String)
myName = value
End Set
End Property
Public Sub ChangeName(ByVal newname As String)
myName = newname
End Sub
Public Sub New(ByVal Name As String, ByVal ID As Integer)
myName = Name
myId = ID
End Sub
End Structure
Public Structure Seminar
Public myPupils As List(Of Pupil)
Private myID As Integer
Private myName As String
Private CurrPupID As Integer
Public Sub New(ByVal Name As String, ByVal ID As Integer)
myPupils = New List(Of Pupil)
myName = Name
myID = ID
CurrPupID = 0
End Sub
Public Sub AddPupil(ByVal Name As String)
Dim NewPupil As New Pupil(Name, CurrPupID)
myPupils.Add(NewPupil)
CurrPupID += 1
End Sub
Public Sub ChangeName(ByVal NewName As String)
myName = NewName
End Sub
Public Function GetPupilByID(ByVal SearchID As Integer) As Pupil
Dim result As New Pupil("", -1)
For Each CurrPup As Pupil In myPupils
If CurrPup.ID = SearchID Then Return CurrPup : Exit Function
Next
Return result
End Function
Public Property ID() As Integer
Get
Return myID
End Get
Set(ByVal value As Integer)
myID = value
End Set
End Property
Public Property Name() As String
Get
Return myName
End Get
Set(ByVal value As String)
myName = value
End Set
End Property
End Structure
Public Structure SchoolHandler
Private mySeminars As List(Of Seminar)
Private currSemID As Integer
Public Sub New(ByVal StartID As Integer)
mySeminars = New List(Of Seminar)
currSemID = StartID
End Sub
Public Sub Add(ByVal Name As String)
Dim NewSem As New Seminar(Name, currSemID)
mySeminars.Add(NewSem)
currSemID += 1
End Sub
Public Function GetSeminarByID(ByVal SearchID As Integer) As Seminar
Dim result As New Seminar
result.ID = -1
For Each CurrSem As Seminar In mySeminars
If CurrSem.ID = SearchID Then Return CurrSem : Exit Function
Next
Return result
End Function
Public Sub ShowAllPupils()
For Each CurrSem As Seminar In mySeminars
Debug.Print(CurrSem.Name)
For Each CurrPup As Pupil In CurrSem.myPupils
Debug.Print(CurrPup.Name)
Next
Debug.Print(vbNewLine)
Next
End Sub
End Structure
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles MyBase.Load
Dim school As New SchoolHandler(1)
school.Add("Mathe")
school.Add("Deutsch")
school.GetSeminarByID(1).AddPupil("Hans")
school.GetSeminarByID(2).AddPupil("Bernd")
school.ShowAllPupils()
school.GetSeminarByID(1).GetPupilByID(1).ChangeName("Georg")
school.GetSeminarByID(1).ChangeName("Sport")
school.ShowAllPupils()
End Sub
End Class
Hier die noch erzeugte Ausgabe:
Mathe
Hans
Deutsch
Bernd
Mathe
Hans
Deutsch
Bernd
Die gewünschte Ausgabe wäre:
Mathe
Hans
Deutsch
Bernd
Sport <-
Georg <-
Deutsch
Bernd Ich vermute das Problem liegt darin das mir durch die Get-Funktionen nur Kopien der Structures zurück gegeben und dann geändert werden. Die Originale im Speicher bleiben unberührt. Nun bekomme ich es einfach nicht hin mir Referenzen auf die Structures zurückgeben zu lassen. Wer könnte mir da einen Tipp geben. Sollte ich mich unklar ausgedrückt haben fragt bitte nach
Vielen Dank | |
Re: Referenz auf Structure zurückgeben | | | Autor: keco | Datum: 17.01.10 17:40 |
| Gibt es einen besonderen Grund, weshalb du Structure verwendest und nicht Class? | |
Re: Referenz auf Structure zurückgeben | | | Autor: Friedel84 | Datum: 17.01.10 17:48 |
| Nein dafür gibs eigentlich keinen Grund. Wenn ich es auf Klassen umstelle bekomme ich folgende Ausgabe:
Mathe
Hans
Deutsch
Bernd
Sport <--klappt
Hans <--klappt nicht (?!)
Deutsch
Bernd
Edit:
Es funktioniert. Das Problem das der Name nicht geändert wurde lag woanders. GetPupilByID(0) hätte das heissen müssen.
Aber die Frage würde mich trotzdem noch interessieren. Wieso geht das mit Structures nicht. Weiß da jemand was?
Beitrag wurde zuletzt am 17.01.10 um 17:55:16 editiert. | |
Re: Referenz auf Structure zurückgeben | | | Autor: keco | Datum: 17.01.10 18:00 |
| Das liegt daran, dass die Person einen falschen Index hat. In der Zeile, wo du die Indizies überprüfst in GetPupilByID ist der Index der Person 0, gesucht wird aber 1.
Ich frage mich sowieso, wieso du das so umständlich machst. Du verwaltest alle Seminare in einer Liste in School. Und alle Schüler in einer Liste in Seminar. Die Liste hat bereits eine Eigenschaft zum abrufen der entsprechenden Person an einem Index.
So in etwa:
Public Class Pupil
Private myName As String
Private myId As Integer
Public Sub New(ByVal Name As String, ByVal ID As Integer)
myName = Name
myId = ID
End Sub
Property ID() As Integer
Get
Return myId
End Get
Set(ByVal value As Integer)
myId = value
End Set
End Property
Property Name() As String
Get
Return myName
End Get
Set(ByVal value As String)
myName = value
End Set
End Property
Public Sub ChangeName(ByVal newname As String)
myName = newname
End Sub
End Class
Public Class Seminar
Private myPupils As List(Of Pupil)
Private myID As Integer
Private myName As String
Public Sub New(ByVal Name As String, ByVal ID As Integer)
myPupils = New List(Of Pupil)
myName = Name
myID = ID
End Sub
Public Sub AddPupil(ByVal Name As String)
myPupils.Add(New Pupil(Name, myPupils.Count))
End Sub
Public Sub ChangeName(ByVal NewName As String)
myName = NewName
End Sub
Public Function GetPupilByID(ByVal SearchID As Integer) As Pupil
Return myPupils(SearchID)
End Function
Public Property ID() As Integer
Get
Return myID
End Get
Set(ByVal value As Integer)
myID = value
End Set
End Property
Public Property Name() As String
Get
Return myName
End Get
Set(ByVal value As String)
myName = value
End Set
End Property
Public ReadOnly Property Pupils() As List(Of Pupil)
Get
Return myPupils
End Get
End Property
End Class
Public Class SchoolHandler
Private mySeminars As List(Of Seminar)
Public Sub New(ByVal StartID As Integer)
mySeminars = New List(Of Seminar)
End Sub
Public Sub Add(ByVal Name As String)
mySeminars.Add(New Seminar(Name, mySeminars.Count))
End Sub
Public Function GetSeminarByID(ByVal SearchID As Integer) As Seminar
Return mySeminars(SearchID)
End Function
Public Sub ShowAllPupils()
For Each CurrSem As Seminar In mySeminars
Debug.Print(CurrSem.Name)
For Each CurrPup As Pupil In CurrSem.Pupils
Debug.Print(CurrPup.Name)
Next
Debug.Print(vbNewLine)
Next
End Sub
End Class
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles MyBase.Load
Dim school As New SchoolHandler(1)
school.Add("Mathe")
school.Add("Deutsch")
school.GetSeminarByID(0).AddPupil("Hans")
school.GetSeminarByID(1).AddPupil("Bernd")
school.ShowAllPupils()
school.GetSeminarByID(0).GetPupilByID(0).Name = "Georg" ' EDIT
school.GetSeminarByID(0).Name = "Sport" ' EDIT
school.ShowAllPupils()
End Sub EDIT: Wertezuweisung geändert. In diesem Fall kannst du auch die ChangeName-Methoden löschen. Sind überflüssig.
Beitrag wurde zuletzt am 17.01.10 um 18:03:06 editiert. | |
Re: Referenz auf Structure zurückgeben | | | Autor: Friedel84 | Datum: 17.01.10 18:06 |
| Also in erster Linie ist das ein fiktives Beispiel das mir auf die schnelle eingefallen ist weil der Code bei dem ich das festgestellt habe viel länger und komplizierter ist ;)
Und den Listenindex habe ich nicht verwendet weil ich mir vorstellen könnte das ein Schüler ne ID bekommt die nicht mit dem Index in der Liste übereinstimmt. Zum Beispiel ne Matrikelnummer oder so.
Aber was mich interessieren würde ist was du mit kompliziert meinst. Würdest du eine andere Hierarchie wählen? Ich fand die Schule als oberbegriff für Seminar und diese als Oberbegriff für Studenten eigentlich ok. Wie wäre es denn einfacher?
Edit ach und natürlich vielen Dank für deinen Einsatz
Beitrag wurde zuletzt am 17.01.10 um 18:07:30 editiert. | |
Re: Referenz auf Structure zurückgeben | | | Autor: keco | Datum: 17.01.10 18:16 |
| Ich dachte dabei an die Verwaltung mit der ID und dem Listenindex. Der Listenindex sollte in allen erdenklichen Fällen vollkommen unabhängig von allen Informationen der Person sein.
Für alle Informationen sollte es Eigenschaften geben. Eben eine Matrikelnummer beispielsweise. Das einzige, was du machen müsstest wäre eine Eigenschaft zu definieren, der du die Matrikelnummer übergibst und diese dir die entsprechende Person zurückgibt.
Zum Beispiel diese Methode in "Seminar": Default Public ReadOnly Property Pupil(ByVal matrikel As Integer) As Pupil
Get
For Each p In myPupils
If p.Matrikel = matrikel Then Return p
Next
Return Nothing
End Get
End Property im Load beispielsweise das: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles MyBase.Load
Dim school As New SchoolHandler(1)
school.Add("Mathe")
school.Add("Deutsch")
school.GetSeminarByID(0).Pupils.Add(New Pupil("Hans", 206000))
school.GetSeminarByID(1).Pupils.Add(New Pupil("Bernd", 206011))
school.ShowAllPupils()
school.GetSeminarByID(0).Pupil(206000).Name = "Georg"
school.GetSeminarByID(0).Name = "Sport"
school.ShowAllPupils()
End Sub | |
Re: Referenz auf Structure zurückgeben | | | Autor: Friedel84 | Datum: 17.01.10 18:23 |
| Ok das ist ne bessere Variante
Aber ich denke wir brauchen hier an der Stelle nicht mehr tiefer auf dieses Programm eingehen.
Sollte noch jemand wissen wieso das mit Structures nicht geht oder was eigentlich genau der Unterschied zwischen Structures und Classes ist dann hat er jetzt hier die möglichkeit ein wenig mit diesem Wissen anzugeben ;)
Ansonsten nochmal vielen Dank für Unterstützung | |
Re: Referenz auf Structure zurückgeben | | | Autor: Friedel84 | Datum: 17.01.10 18:31 |
| Ahh okay das liegt soweit erstmal ziemlich logisch. Wirft für mich aber noch eine Frage auf. Muss ich da jetzt spezielle Aufräummaßnahmen einleiten wenn ich etwas entferne. A là Gc.Collect oder ähnliches? | |
Re: Referenz auf Structure zurückgeben | | | Autor: keco | Datum: 17.01.10 18:33 |
| Nein, der GC erledigt seine Arbeit von selbst. Allerdings musst du dafür Sorge tragen, dass das Objekt auch als ungültig erklärt wird. Also ein Objekt immer schon disposen, wenn es nicht mehr gebraucht wird (sofern es IDisposable implementiert) oder zumindest alle Referenzen auf dieses Objekt löschen. | |
Re: Referenz auf Structure zurückgeben | | | Autor: Friedel84 | Datum: 17.01.10 18:36 |
| Ok alles klaro! Dann nochmal ein großes Dankeschön und bis zum nächsten Problem ;)
-> solved and closed | |
| 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 |
|
|
Neu! sevEingabe 3.0
Einfach stark!
Ein einziges Eingabe-Control für alle benötigten Eingabetypen und -formate, inkl. Kalender-, Taschenrechner und Floskelfunktion, mehrspaltige ComboBox mit DB-Anbindung, ImageComboBox u.v.m. Weitere InfosTipp des Monats Access-Tools Vol.1
Über 400 MByte Inhalt
Mehr als 250 Access-Beispiele, 25 Add-Ins und ActiveX-Komponenten, 16 VB-Projekt inkl. Source, mehr als 320 Tipps & Tricks für Access und VB
Nur 24,95 EURWeitere Infos
|