VS.NET 2005 issue with array of structures

Vandel

Member
Joined
Feb 8, 2011
Messages
5
Programming Experience
10+
VB6 you can do record=record.

Apparently under .NET you can't, or at least in the version of VS.NET I'm using. It breaks.

Symptom reproduction...

PublicStructure Data_Record
Public Key_Result() AsLong
Public Key_Size AsLong
Public Key_OP AsByte
Public Key_IP AsByte
Public Distance AsLong
Public Palindrome AsString
Public Lychrel_Chain AsString
Public Hits AsLong
EndStructure

Sub Main()
Dim ll AsLong
Dim a() As Data_Record

ReDim a(5)
For ll = 1 To 5
ReDim a(ll).Key_Result(1)
Next ll

a(1).Key_Size = 1
a(1).Key_Result(1) = 1
a(2) = a(1)
a(2).Key_Size = 2
a(2).Key_Result(1) = 2
a(3) = a(2)
a(3).Key_Size = 3
a(3).Key_Result(1) = 3
End Sub

If I throw a watch on array 'a' I get what I believe is a pointer assignment problem internally to the array structure affecting the value of the changing .key_result.

a(1).key_size=1
a(1).key_result(1)=3
a(2).key_size=2
a(2).key_result(1)=3
a(3).key_size=3
a(3).key_result(1)=3

The same code in VB6 produces...

a(1).key_size=1
a(1).key_result(1)=1
a(2).key_size=2
a(2).key_result(1)=2
a(3).key_size=3
a(3).key_result(1)=3

Which is the correct assignment of values. VS.NET for some reason literally as far as I can tell is pointing the second dynamic array of all prior records affected by a record=record that were done so in succession of eachother to the value of the last record=record assignment.

I tried array.copy also, and it failed the same way.

Ultimately a(2).key_result = a(1).key_result and progressing them directly without doing a direct a(2)=a(1) reference, maintains the integrity of the seperation and no corruption of data occurs in the .key_result dynamic array. I guess if I have to just bloat the code to circumvent this, then so be it... but I was hoping for .NET to be a little more gracious.

Any ideas? The SP for VS2005 didn't fix this issue. And I've not been able to find any references to this anywhere. Did this suddenly become bad coding methodology in .NET, or have I found an uncorrected/unrecognized bug?

Can anyone with a later version of VS.NET report if this mangling of array structures still occurs in 2008, or 2010? This is just one of many troubling concerns I have with making the transition to .NET from VB6.0, regardless of the fact that VB6.0 is at its end of life cycle, at least it works correctly. I get some things are easier in .NET, but what good is ease of use, if the language itself seems to be so picky about how you assign variables?

 
Last edited:
VB.NET works fine. You're just not using it properly. The important thing here is the difference between value types (structures, enumerations) and reference types (classes, delegates). A value type variable contains the object itself, while a reference type variable contains a reference to an object elsewhere. What this means is that assigning a value type creates a copy of the object, while assigning a reference type creates a copy of the reference, so there's still only one object. Once you understand the ramifications of this, the behaviour of classes and structures seems completely logical.

In your case, your Data_Record type should absolutely be a class rather than a structure. One significant rule of thumb is that a structure should never be over 16 bytes in size. Yours is 38. You should make that change for a start, and you'll find that things will change somewhat. The vast majority of types should be classes, with structures only used where it specifically makes sense. If you don't know the difference between classes and structures and the way they behave then you can't really know where it specifically makes sense to use a structure, so you should pretty much stick to classes to begin with.
 
VB.NET works fine. You're just not using it properly.

Couldn't help but laugh from that. If I'm not using it correctly, the compiler should have told me. It referenced 101 errors for nearly 2 days when I was porting the code from VB6 to .NET and it never complained about the usage of the structures. Old Record Type Definitions in VB6.0 had a 64k limit. Doing some reading up, structures exist on the stack, so I get the 16 byte reference now you made. Might wanted to have pointed that out, it wasn't obvious to be right away. But that doesn't stop structures from going over 16 bytes... if you're concerned about speed and what not.

I get the difference between ByVal and ByRef, unfortunately the VS.NET environment told me change the Old VB6.0 Type to Structure. So that's what I did, making it sound like it was a direct equivalent. If I should have used a Class, maybe is should have suggested that instead. If structures are essentually muted at this point, why have them at all? This is the same complaint with JAVA that the C/C++ style structures were dumped leaving you with container classes similar to what .NET is basically doing. I'm spending less and less time coding, and more and more time figuring out the blooming intricacies of a language making very simple code seem way way more complicated than it should be.

The important thing here is the difference between value types (structures, enumerations) and reference types (classes, delegates).

So, I want structures then, individual byVal copies so they work like they did in VB6.0, not a byRef class using pointer arguments for passing during reassignment, which is closer to what I'm seeing with the structures that you're claiming are supposed to be byVal copies, and not direct pointing assignments on the second dynamic array containng the .key_result. Unfortunately, that's exactly what I'm seeing. According to the IDE the entire project is class of classes. I've been avoiding the .NET migration for nearly 6 years because of the obfuscations I saw when I first tried to move over to .NET. I'll state quite clearly, I'm still thoroughly unimpressed. However, Since I don't have a choice, I'm making the transition kicking and screaming.

Once you understand the ramifications of this, the behaviour of classes and structures seems completely logical.

What I think is more clear here is that .NET handles them completely differently than all prior version of MS BASIC Compilers. If I shift to a class structure, then I need to start thinking linked lists? Or do I shift to an array of objects as opposed to an array of structures? I'm confused also by an article I had that claims I need to 'NEW' each instance of a structure now also because they're essentially just tiny classes.

To make this work like old VB6.0 so I can keep track of what the heck is going on, what would it change to?

I fully understood how Type vs Class worked in VB6.0. I clearly am missing something in how Structure vs. Class works in .NET. Maybe MS should have been a little more clear on the references in the language. I'm also finding a lot of the C/C++ style annotations of code migration to have mutilated BASIC along the same lines as what Borland did to DBase when they bought it back in 1996 when they did a fusion langauge with C/C++ hooks directly accessible by framework in DBase. I'm confused enough with about 20 different ways of working with filestreams, none of which I can get to work. And what's with writeln()? That's Pascal/Delphi, what happened to PRINT that's BASIC.. What was wrong with the good old days of OPEN. Like if it ain't broke, don't fix it. I can't get file streams to work properly either. They dumped app.path... the string$ function abandoned... they changed the order of the strcomp function. What I'm finding is this is more like RELEARNING a whole new version of BASIC that is no longer BASIC, it just looks like it very very loosely based on BASIC.

<END RANT>

So... I humored you... just to check the class style byRef... which is NOT what I want with individual byVal copies that should be inherited across the structure from being contained in a byVal structure.

PublicClass Data_Record
Public Key_Result() AsLong
Public Key_Size AsLong
Public Key_OP AsByte
Public Key_IP AsByte
Public Distance AsLong
Public Palindrome AsString
Public Lychrel_Chain AsString
Public Hits AsLong
EndClass

Sub Main()
Dim ll AsLong
Dim a() As Data_Record
ReDim a(5)
For ll = 1 To 5
a(ll) = New Data_Record
ReDim a(ll).Key_Result(1)
Next ll
a(1).Key_Size = 1
a(1).Key_Result(1) = 1
a(2) = a(1)
a(2).Key_Size = 2
a(2).Key_Result(1) = 2
a(3) = a(2)
a(3).Key_Size = 3
a(3).Key_Result(1) = 3
End Sub

The result of the array is even worse off since the class is doing a byRef assignment and the entire dataset is now changing to

a(1).key_size=3
a(1).key_result(1)=3
a(2).key_size=3
a(2).key_result(1)=3
a(3).key_size=3
a(3).key_result(1)=3

WHICH if the structures were working correctly doing a byVal copy... I should get...


a(1).key_size=1
a(1).key_result(1)=1
a(2).key_size=2
a(2).key_result(1)=2
a(3).key_size=3
a(3).key_result(1)=3


From this it would tell me I want a Structure, NOT A CLASS... the structure was closer to the right answer but was treating the .key_result imbedded dynamic array as a byRef class pointer instead of the byVal copy that it should have inherited from the fact it was imbedded in a STRUCTURE.

I tried using a class prior... and it was even more broken than the structure that is 50% correct.

When it was a structure... everything in the structure except the .key_result being referenced as though it was part of a Class and being treated byRef...

Which is why I did a .key_result=.key_result assignment to find that it then did the differentiation of the byVal COPY properly in the structure, which I why I outlined that reference.

I think you missed the point of the original post. That part of the structure was acting byVal and part of the structure specifically the .key_result was acting byRef. Two distinct states existing in something that should have only one, and it should have been BYVAL throughout the structure. Not deciding that the .key_result should suddenly be treated byRef.

If I'm still not understanding this clearly, can you supply some code?
 
Last edited:
I think that Key_Result() is not copying "values" from one element to the next is because "array" is a class itself... Making an "=" assignment from it will be ByRef... as it is for ALL of your variables when you use a Class for Data_Record rather than a Structure... Yes ???
 
[MASSIVE EDIT]

@ALX: You're correct, after digging around a bunch it turns out VB.NET uses C/C++ style byRef arrays and not the byVal copy array regardless of their placement in a structure as they're pulled from the class collection during declaration.

SOOOOO... What MS should have declared and JMCILHINNEY could have saved me some time by making that very statement. So Arrays declared in Structures because they are a Class declaration will ALWAYS be treated byRef.

So a variable assignment on the record level of a structure containing an array will byVal all non-array variables, and byRef the array.

During a variable element to element assignment of an array from the structure will do a byVal copy, which is what I'm seeing.

This is a case where you totally have to read the fine print. And the documents on the MSDN site do not allude to this being the case.

They need to have an exlusion in the structure explantions to points this out. Or something more specific.

Hopefully this will save someone else the severe headaches this has caused me. Be well...
 
Last edited:
It seems that there has always been a lack of documentation for VS20xx all along, and I've depended on this forum to help me out through that. JMC and John will always help you out when you really need it, and I'm extremely grateful for their help over the years. Keep a thick skin... What these guys will show you is better than you'd get in a classroom!
 
SOOOOO... What MS should have declared and JMCILHINNEY could have saved me some time by making that very statement.
Value Types and Reference Types

ByVal and ByRef is not the same, these are the arguments passing mechanism for method parameters. You may very well use either one for both value types and reference types, but essentially ByRef is only used when you want to be able to reassign/dereference the callers variable. A ByVal for a reference type will give you the same as when assigning an object reference to a new variable, ie just a copy of the address reference.
 
[EDIT JohnH, on that page you supplied is the reference to all arrays being treated byRef which is what I was actually looking for... and what AXL has already pointed out...]

I hate to sound a jerk, but I know I'm going end up sounding like one by time I'm through with this thread... JohnH and JMCHILHINNEY have completely missed the point of this thread. I am well aware of what byVal and byRef do. It's not a question of how they work. If you both ACTUALLY read the posts I've supplied, you would understand this is more about the differences between UTD in VB6.0 and Structures in VB.NET not treating Arrays the same and should not at all be declared direct equivalents. As moderators I would have expected both of you to pay a lot more attention to this.

I appreaciate what you're trying to do here, but PLEASE read what I've written and respond in the context of what my actual problem was, instead of instantly jumping to conclusions that this is just a simple case of not understanding the differences between byVal and byRef. What this has turned out to be is a case of very poorly documented modifications and changes to the structures and methodologies of the language between VB6.0 and VB.NET.

ALX got the point... pay attention to what he wrote. His response was WAY more useful than what either of you supplied, when he pointed out that ARRAYS are derived from CLASSES. So despite my understanding of byVal and byRef here, it didn't matter because I was making an assumption that arrays in structures were going to act like they did in VB6.0, and continue to be treated byVal like the rest of the structure, instead of arrays being treated byRef by declaration. Knowledge of what you have pointed out is no more useful than what Microsoft has supplied. When they alluded that all variable elements declared in a structure would be treated byVal... and then pay more careful attention to my last post, where I made refrence to what AXL wrote into the actual solution to the problem here.

Sheesh... I seriosly hope you pay more attention to other peoples posts because here you've really not helped the situation at all.

I'll spell it out...

Structure...
Non-Array elements are always treated byVal
Array elements are treated byRef during a record=record style assignment, and treated byVal during an array element=array element assignment.

Class...
Non-Array and Array elements are always treated byRef.

When Microsoft made the declartion of structures here Structures and Classes they specifically reference...

Assigning Variables. When you assign one structure variable to another, or pass a structure instance to a procedure argument, the current values of all the variable elements are copied to the new structure.

THIS IS NOT THE CASE WHEN ARRAYS ARE INVOLVED!

If you take this and go back and read my original post that started the thread maybe this will make more sense to you both and what caused the initial confusion. This may be blatantly evident to both of you, but is not immediately evident to someone coming from VB6.0 with expectations that the language may have some updates, but not be completely changing syntax and methods of the actual language without properly documenting them... [edit... or in this case generating documentation that conflicts itself].
 
Last edited:
the current values of all the variable elements are copied to the new structure.
THIS IS NOT THE CASE WHEN ARRAYS ARE INVOLVED!
Yes it is, because a reference type variable does only contain a memory pointer, which is simply copied to the new structure member.

About VB6 I suggest you place all of that in a nice box and bury it.
 
ByRef is only used when you want to be able to reassign/dereference the callers variable.

This is profound! What started all this confusion is that we should have been saying "Reference Type" or "Value Type" instead of "ByRef" and "ByVal". This is something that I hadn't even thought about until John spelled it out here, and it's what makes this such a valuable resource. Vandel, it is our own incorrect terminology that led us down this BS path.The responses here are trying to give the WHOLE picture, not simply an answer to a question. Going from VB6.0 to Visual Studio might be a pain... I came to VS from Basic... The old DOS Basic... 'Talk about having to rethink the logistics!!! It's hard to change your way of thinking. A little humility here will get you loads of goods!
 
Last edited:
Back
Top