Scott McDaniel (EE MVE )
asked on
VB.NET List(of) unable to update list elements
I have a Structure declared like this:
Private Structure stCat
Public CatID As Integer
Public IsOnsite As Boolean
Public RndNum As Integer
End Structure
I have a List(of) declared like this:
Private colJudgeCats As List(Of stCat)
I fill that List like this:
The Dataset (dsCats) contains the data, and the data fills correctly (currently from an Access database).
I then attempt to update the data in the List like this:
I recieve a compile error this, with this section highlighted:
colJudgeCats(i).IsOnsite
The Error is "Expression is a value and therefore cannot be the target of an assignment"
I can get around this by using classes (which is what I've done), but I was curious as to why I'm not able to update a Member of a List in this fashion. Is there something I'm missing, or can I not use a List in this fashion? Should I use some other form of collection object? I don't want to use Datasets for various reasons, and would instead prefer to allow each of my classes to maintain their own collections/lists.
Private Structure stCat
Public CatID As Integer
Public IsOnsite As Boolean
Public RndNum As Integer
End Structure
I have a List(of) declared like this:
Private colJudgeCats As List(Of stCat)
I fill that List like this:
colJudgeCats = New List(Of stCat)
For Each dtrCats As DataRow In dsCats.Tables(0).Rows
Dim pCat As New stCat
With pCat
.CatID = dtrCats.Item("iCatID")
.IsOnsite = dtrCats.Item("bOnSite")
End With
colJudgeCats.Add(pCat)
Next
The Dataset (dsCats) contains the data, and the data fills correctly (currently from an Access database).
I then attempt to update the data in the List like this:
Public Function AddJudgeToCategory(ByVal CatID As Long, ByVal IsOnsite As Boolean) As Boolean
Dim i As Integer
For i = 0 To colJudgeCats.Count
If colJudgeCats(i).CatID = CatID Then
colJudgeCats(i).IsOnsite = IsOnsite
End If
Next
End Function
I recieve a compile error this, with this section highlighted:
colJudgeCats(i).IsOnsite
The Error is "Expression is a value and therefore cannot be the target of an assignment"
I can get around this by using classes (which is what I've done), but I was curious as to why I'm not able to update a Member of a List in this fashion. Is there something I'm missing, or can I not use a List in this fashion? Should I use some other form of collection object? I don't want to use Datasets for various reasons, and would instead prefer to allow each of my classes to maintain their own collections/lists.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Adding to kaufmed's great response...if you want to use your original code then change from a struct to a class.
>> Adding to kaufmed's great response...
I didn't think it was that great :\ Hopefully this will redeem it.
When you index the list, you are receiving a copy of your structure and not the actual object at that location--you can thank the value-typedness for that. As such, you would be assigning to the copy and not the actual data store where structure is held. When you assign a new struct back to the list at index "foo", you are basically overwriting the entire struct value at that memory location.
I didn't think it was that great :\ Hopefully this will redeem it.
When you index the list, you are receiving a copy of your structure and not the actual object at that location--you can thank the value-typedness for that. As such, you would be assigning to the copy and not the actual data store where structure is held. When you assign a new struct back to the list at index "foo", you are basically overwriting the entire struct value at that memory location.
ASKER
<if you want to use your original code then change from a struct to a class>
That's what I'd done already (see my original post) and of course it works. I was just curious as to why I couldn't write directly to the List item/element.
So I would assume that you can't directly change the elements of a List's object through any means? You must build a new item of the same "type" as the List item, and then assign that new item to the List at the Index of the item you're replacing?
That's what I'd done already (see my original post) and of course it works. I was just curious as to why I couldn't write directly to the List item/element.
So I would assume that you can't directly change the elements of a List's object through any means? You must build a new item of the same "type" as the List item, and then assign that new item to the List at the Index of the item you're replacing?
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>> You must build a new item of the same "type" as the List item
Only when dealing with value types in the list.
Only when dealing with value types in the list.
ASKER
Thanks for that. I did some reading on the subject and understand much better than I did earlier. Seems a lot like the old "ByRef" and "ByVal" modifiers in VB6.
For my purposes, which is better: A List of Structures, or a List of Classes? My goal is to have a collection of child objects available from a Parent class. There will be little "work" done on those child collections. In essence, I just need to (a) know how many children are associated with a Parent and (b) manipulate a single bit of data for each (change the IsOnsite value from True to False or vice-versa), based on user interaction.
Thanks again for your time. My knowledge of VB.NET is increasing all the time, but I'm still far from an Expert in these matters.
For my purposes, which is better: A List of Structures, or a List of Classes? My goal is to have a collection of child objects available from a Parent class. There will be little "work" done on those child collections. In essence, I just need to (a) know how many children are associated with a Parent and (b) manipulate a single bit of data for each (change the IsOnsite value from True to False or vice-versa), based on user interaction.
Thanks again for your time. My knowledge of VB.NET is increasing all the time, but I'm still far from an Expert in these matters.
>> Seems a lot like the old "ByRef" and "ByVal" modifiers in VB6.
Those same modifiers still exist in VB.NET. It gets a little counter-intuitive (from a value type vs ref type perspective) when you start talking about value types ByRef. An explanation passing mechanisms is here: http://msdn.microsoft.com/en-us/library/aa903254%28v=VS.71%29.aspx
>> For my purposes, which is better
It sounds like your data is small (which is a candidate for structs) and that you're not planning on reusing/deriving from the container. You should be fine with structs as long as you perform the assignments as previously described, unless of course you don't want to do assignments in that manner; then go with a class so you can interact directly with the member.
You may be interested to know that structures are allocated on the stack whereas classes are allocated on the heap.
Tidbit: In case you weren't aware, you can actually have constructors and methods on structures in VB.NET (and .NET in general). Also, strings are reference types, but they act like value types.
Those same modifiers still exist in VB.NET. It gets a little counter-intuitive (from a value type vs ref type perspective) when you start talking about value types ByRef. An explanation passing mechanisms is here: http://msdn.microsoft.com/en-us/library/aa903254%28v=VS.71%29.aspx
>> For my purposes, which is better
It sounds like your data is small (which is a candidate for structs) and that you're not planning on reusing/deriving from the container. You should be fine with structs as long as you perform the assignments as previously described, unless of course you don't want to do assignments in that manner; then go with a class so you can interact directly with the member.
You may be interested to know that structures are allocated on the stack whereas classes are allocated on the heap.
Tidbit: In case you weren't aware, you can actually have constructors and methods on structures in VB.NET (and .NET in general). Also, strings are reference types, but they act like value types.
ASKER
The data contained in those structures would be small (no more than 8 members, I'd think, with a mix of numeric and small text). I think I'm going to move to Structures for this instead of Classes. I'm just startint this project and haven't finalized any real architecture yet.
Are there any performance issues with the two methods? I can't imagine there would be with my very simple data needs, but what happens as the datasets become larger and/or more complex?
I saw quite a few discussions on stack and heap, and while I have a working knowledge of those concepts I've marked a few of the more interesting articles for future reading.
I did seem some discussion regarding adding Methods and such to STructures. Seems to me that if you're at that point, you'd be better off with Classes, but I suppose there was a reason for including that functionality. I could perhaps see where a very simple method (like Strct.X = Strct.Y - Strct.Z) would be useful, but anything further would seem to be moving into the Class area.
Are there any performance issues with the two methods? I can't imagine there would be with my very simple data needs, but what happens as the datasets become larger and/or more complex?
I saw quite a few discussions on stack and heap, and while I have a working knowledge of those concepts I've marked a few of the more interesting articles for future reading.
I did seem some discussion regarding adding Methods and such to STructures. Seems to me that if you're at that point, you'd be better off with Classes, but I suppose there was a reason for including that functionality. I could perhaps see where a very simple method (like Strct.X = Strct.Y - Strct.Z) would be useful, but anything further would seem to be moving into the Class area.
>> Are there any performance issues with the two methods?
Yes. If you make large structures, any time you return them from a function (or access them in a List) you are returning a copy of a large structure--every time you perform such access (barring ByRef params). This is why you typically use structs for small sets of data.
As far as methods on structs, think about it this way: you've got methods like int.TryParse(), Point.Offset(), and Color.FromArgb(), to name a few. All are methods of structs. As with any project, it takes good forethought and design :)
Yes. If you make large structures, any time you return them from a function (or access them in a List) you are returning a copy of a large structure--every time you perform such access (barring ByRef params). This is why you typically use structs for small sets of data.
As far as methods on structs, think about it this way: you've got methods like int.TryParse(), Point.Offset(), and Color.FromArgb(), to name a few. All are methods of structs. As with any project, it takes good forethought and design :)
ASKER
Great points. Thanks for the insight and assistance.
NP. Glad to help :)