Link to home
Start Free TrialLog in
Avatar of Scott McDaniel (EE MVE )
Scott McDaniel (EE MVE )Flag for United States of America

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:

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

Open in new window


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

Open in new window


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
Avatar of kaufmed
kaufmed
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
Avatar of Scott McDaniel (EE MVE )

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?

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> You must build a new item of the same "type" as the List item

Only when dealing with value types in the list.
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.
>>  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.
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?

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  :)
Great points. Thanks for the insight and assistance.
NP. Glad to help  :)