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.
LVL 86
Scott McDaniel (Microsoft Access MVP - EE MVE )Infotrakker SoftwareAsked:
Who is Participating?
 
käµfm³d 👽Commented:
Since your dealing with a value type (struct), you have to assign a whole "new" object to the overall "object"; you cannot assign to the members directly, at least not when they are stored in a List. The following would work:
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
			Dim temp As New stCat

			temp.CatID = colJudgeCats(i).CatID
			temp.RndNum = colJudgeCats(i).RndNum
			temp.IsOnsite = IsOnsite

			colJudgeCats(i) = temp
		End If
	Next

End Function

Open in new window

0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Adding to kaufmed's great response...if you want to use your original code then change from a struct to a class.
0
 
käµfm³d 👽Commented:
>>  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.
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
Scott McDaniel (Microsoft Access MVP - EE MVE )Infotrakker SoftwareAuthor Commented:
<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?

0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
You can directly change it in the List() if you use a CLASS.

As kaufmed stated, when you use a struct, a COPY of the struct is made and that is what you are actually modifying.  Structs are VALUE types, as opposed to a reference types, thus you are working with copies.

Look up the difference between a value type and a reference type on MSDN.
   
0
 
käµfm³d 👽Commented:
>> You must build a new item of the same "type" as the List item

Only when dealing with value types in the list.
0
 
Scott McDaniel (Microsoft Access MVP - EE MVE )Infotrakker SoftwareAuthor Commented:
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.
0
 
käµfm³d 👽Commented:
>>  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.
0
 
Scott McDaniel (Microsoft Access MVP - EE MVE )Infotrakker SoftwareAuthor Commented:
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.
0
 
käµfm³d 👽Commented:
>>  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  :)
0
 
Scott McDaniel (Microsoft Access MVP - EE MVE )Infotrakker SoftwareAuthor Commented:
Great points. Thanks for the insight and assistance.
0
 
käµfm³d 👽Commented:
NP. Glad to help  :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.