Solved

VB.NET List(of) unable to update list elements

Posted on 2010-11-15
12
3,052 Views
Last Modified: 2012-05-10
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.
0
Comment
  • 6
  • 4
  • 2
12 Comments
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 400 total points
ID: 34141156
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
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 34141250
Adding to kaufmed's great response...if you want to use your original code then change from a struct to a class.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34141273
>>  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
 
LVL 84
ID: 34141532
<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
 
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 100 total points
ID: 34141713
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
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34141896
>> You must build a new item of the same "type" as the List item

Only when dealing with value types in the list.
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 84
ID: 34143983
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
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34144499
>>  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
 
LVL 84
ID: 34144539
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
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34144770
>>  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
 
LVL 84
ID: 34144927
Great points. Thanks for the insight and assistance.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34145172
NP. Glad to help  :)
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

This is an explanation of a simple data model to help parse a JSON feed
Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now