Can't assign value to structure in array?

B

Brett

I have created a structure with five fields. I then create an array of this
type of structure and place the structure into an array element. Say index
one. I want to assign a value to field3 of the structure inside the array.
When I try this, an error about late assignment appears. Is it possible to
assign a value to a structure field that is in an array?

I'm currently getting around the problem by creating a new structure, assign
the structure fields using values in the arary...minus field 3, which gets a
value from somewhere else. I then place this structure into the array.

Thanks,
Brett
 
J

Jonathan Allen

All structures should be immutable. If is it possible to change the
structure in any perceivable way, then chances are it will be used
incorrectly. For example, if you return the structure from a property, one
may think that changing the structure will change the class.

myClass.myStructProperty.myValue = 5;

this compiles as...

aStruct temp = myClass.myStructProperty;
temp.myValue = 5;
//throw away temp and its new value.




********

As for you specific problem, post the code.
 
N

Nicholas Paldino [.NET/C# MVP]

Brett,

That's pretty much the way that you have to do it. It's the same
problem you would have if you were to return a structure from a property on
a class. Since a copy is returned, you have to store the copy, then
reassign it.

Hope this helps.
 
B

Brett

Ok, you confirmed that is the way to do it but why?. Why exactly can't I
assign values to the structure fields that are in the array but can when
they aren't in the array?

If it were just a simple array element I could assign a value.


Thanks,
Brett
Nicholas Paldino said:
Brett,

That's pretty much the way that you have to do it. It's the same
problem you would have if you were to return a structure from a property
on a class. Since a copy is returned, you have to store the copy, then
reassign it.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Brett said:
I have created a structure with five fields. I then create an array of
this type of structure and place the structure into an array element. Say
index one. I want to assign a value to field3 of the structure inside
the array. When I try this, an error about late assignment appears. Is it
possible to assign a value to a structure field that is in an array?

I'm currently getting around the problem by creating a new structure,
assign the structure fields using values in the arary...minus field 3,
which gets a value from somewhere else. I then place this structure into
the array.

Thanks,
Brett
 
N

Nicholas Paldino [.NET/C# MVP]

Brett,

Here is the reason why. Say you have the following structure
declaration:

public struct MyStruct
{
public int MyInt;
}

Then you have this array:

// Create an array with three elements.
MyStruct[] structs = new MyStruct[3];

At that point, you have an array of three structures with MyInt values
of 0. Now when you do this:

// Assign MyInt on the first element of the array.
structs[0].MyInt = 2;

The statement structs[0] returns a copy of the element in the array, and
you end up setting the MyInt field on the copy, not the original.

Now, this should not give you a compiler error, but it's definitely not
behavior that you want. I am curious what the code is that is giving you
the error.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Brett said:
Ok, you confirmed that is the way to do it but why?. Why exactly can't I
assign values to the structure fields that are in the array but can when
they aren't in the array?

If it were just a simple array element I could assign a value.


Thanks,
Brett
Nicholas Paldino said:
Brett,

That's pretty much the way that you have to do it. It's the same
problem you would have if you were to return a structure from a property
on a class. Since a copy is returned, you have to store the copy, then
reassign it.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Brett said:
I have created a structure with five fields. I then create an array of
this type of structure and place the structure into an array element.
Say index one. I want to assign a value to field3 of the structure
inside the array. When I try this, an error about late assignment
appears. Is it possible to assign a value to a structure field that is
in an array?

I'm currently getting around the problem by creating a new structure,
assign the structure fields using values in the arary...minus field 3,
which gets a value from somewhere else. I then place this structure
into the array.

Thanks,
Brett
 
B

Brett

Here's the code. It's in VB.NET but you can see well what is going on. I'm
converting to C# but wanted to get past this first.

For x As Integer = 0 To ParsedMessage.Length - 1

'create space for new array element
ReDim Preserve imageMapInfoArr(x)

' copy into new structure
imageMapInfo.TickCount_ = ParsedMessage(x).TickCount_
imageMapInfo.Server_StatusCode = ParsedMessage(x).Server_StatusCode
imageMapInfo.URLDestination = ParsedMessage(x).URLDestination
imageMapInfo.ImageURLInSourceText = strImageMapImage
imageMapInfo.URLSourceType = "Image Map"
imageMapInfo.URLSource = ParsedMessage(x).URLSource
imageMapInfoArr(x) = imageMapInfo
Next

I can't do something like:
ParsedMessage(x).URLSourceType = "Image Map"

That's why I'm doing it like the above.

Thanks,
Brett

Nicholas Paldino said:
Brett,

Here is the reason why. Say you have the following structure
declaration:

public struct MyStruct
{
public int MyInt;
}

Then you have this array:

// Create an array with three elements.
MyStruct[] structs = new MyStruct[3];

At that point, you have an array of three structures with MyInt values
of 0. Now when you do this:

// Assign MyInt on the first element of the array.
structs[0].MyInt = 2;

The statement structs[0] returns a copy of the element in the array,
and you end up setting the MyInt field on the copy, not the original.

Now, this should not give you a compiler error, but it's definitely not
behavior that you want. I am curious what the code is that is giving you
the error.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Brett said:
Ok, you confirmed that is the way to do it but why?. Why exactly can't I
assign values to the structure fields that are in the array but can when
they aren't in the array?

If it were just a simple array element I could assign a value.


Thanks,
Brett
Nicholas Paldino said:
Brett,

That's pretty much the way that you have to do it. It's the same
problem you would have if you were to return a structure from a property
on a class. Since a copy is returned, you have to store the copy, then
reassign it.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I have created a structure with five fields. I then create an array of
this type of structure and place the structure into an array element.
Say index one. I want to assign a value to field3 of the structure
inside the array. When I try this, an error about late assignment
appears. Is it possible to assign a value to a structure field that is
in an array?

I'm currently getting around the problem by creating a new structure,
assign the structure fields using values in the arary...minus field 3,
which gets a value from somewhere else. I then place this structure
into the array.

Thanks,
Brett
 
J

Jon Skeet [C# MVP]

Nicholas Paldino said:
Here is the reason why. Say you have the following structure
declaration:

public struct MyStruct
{
public int MyInt;
}

Then you have this array:

// Create an array with three elements.
MyStruct[] structs = new MyStruct[3];

At that point, you have an array of three structures with MyInt values
of 0. Now when you do this:

// Assign MyInt on the first element of the array.
structs[0].MyInt = 2;

The statement structs[0] returns a copy of the element in the array, and
you end up setting the MyInt field on the copy, not the original.

That's not actually true. Try this, for example:

using System;
using System.Drawing;

class Test
{
static void Main()
{
Point[] p = new Point[50];
p[0].X=5;
Console.WriteLine (p[0]);
}
}

The result is:
{X=5,Y=0}

Arrays are treated as sets of variables, effectively - even the C#
language specification talks about them that way. Note that this is
very different from the behaviour you'd get if you were using an
indexer, or a property.
 
J

Jon Skeet [C# MVP]

Brett said:
I have created a structure with five fields. I then create an array of this
type of structure and place the structure into an array element. Say index
one. I want to assign a value to field3 of the structure inside the array.
When I try this, an error about late assignment appears. Is it possible to
assign a value to a structure field that is in an array?

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.

Being in an array shouldn't be a problem in itself. Here's an example
of what it sounds like you're doing:

using System;
using System.Drawing;

struct Foo
{
public int Field1;
public int Field2;

public override string ToString()
{
return string.Format("{0}/{1}", Field1, Field2);
}
}

class Test
{
static void Main()
{
Foo[] f = new Foo[10];
f[0].Field1=10;
f[1].Field2=5;

Console.WriteLine (f[0]);
Console.WriteLine (f[1]);
}
}
 
B

Bruce Wood

Note that it makes a big difference whether it is an array:

MyStruct arr = new MyStruct[15];

....or a collection:

ArrayList arr = new ArrayList();
arr.Add(new MyStruct());
....etc.

In the first case, as Jon pointed out, .NET stores the array of a
contiguous chunk of memory containing the values for all of the
structs. In the second case, the structs are boxed and references to
the structs are stored in the ArrayList.

In the first case you can do things like

arr[9].Property = 5;

and it works. In the second case, you can't, because the struct must be
boxed when it's put in the ArrayList, and unboxed when it's removed, so
you only ever get a copy back.

As Jonathan pointed out, structs should, in general, be immutable. To
change a value in a struct you should construct a new one using values
from the old one (except for the value you want to change). Creating
mutable structs is just asking for trouble. In fact, if you're creating
a mutable struct, it begs the question of why you made it a struct to
start with. Why isn't it a class?
 
T

Ted Miller

That error message is a big red flag telling you that this should not be a
struct, but should be a class instead. There's very little reason to use
structs in .Net programming -- use them only when you need a new thing
that's treated and manipulated immutably.
 
B

Brett

It is an arraylist and not an array so what you have said makes sense. Ok,
a couple have suggested this should possibly be a class. I still don't get
why people are saying the thing I'm doing is a red flag. I'm trying to
reassign values to structure fields within one element of an array. I know
the particular element and the fields of the structure within that element.
So it isn't as if there are other areas in the program that are also
accessing this structure in the same arraylist element.

My flow goes like this:
1. create new structure and assign values
2. put structure into arraylist position (i.e. position 2)
3. new conditions have created values that need to be assigned to certain
structure fields in position two of the arraylist
4. loop through arraylist and assign structure values to a database

My point is that the structure is access only three times. Two writes and
one read. This isn't complicated and I don't have to worry about
accidentally assigning a value to the structure while it is being read
somewhere else. That can't happen since the flow is procedural. I believe
that is the red flag some of you were thinking about.

Please elaborate on the above of where I may be wrong or have
misinterpreted.

Thanks,
Brett
 
B

Bill Butler

My point is that the structure is access only three times. Two writes and
one read. This isn't complicated and I don't have to worry about
accidentally assigning a value to the structure while it is being read
somewhere else. That can't happen since the flow is procedural. I
believe that is the red flag some of you were thinking about.

SO....Why are you making it a struct?

If you make it a class instead it will work.

Bill
 
F

Frank Hileman

Actually mutable structs are very useful. It is inefficient or inconvenient
at times to copy all fields from the old struct, instead of simply changing
one field. The confusion stems from the fact that C# does not distinguish in
any way between value type and reference type modifications. But the
compiler does catch attempts to modify a temporary struct returned from an
indexer.

For example, if you have a struct with 6 32-bit fields, and you wish to
change one field in each struct in a large array, only a mutable struct will
allow you to do this efficiently. A class would add heap overhead and an
extra pointer dereference.

Regards,
Frank Hileman

check out VG.net: http://www.vgdotnet.com
Animated vector graphics system
Integrated Visual Studio .NET graphics editor
 
J

Jonathan Allen

For example, if you have a struct with 6 32-bit fields, and you wish to
change one field in each struct in a large array, only a mutable struct
will allow you to do this efficiently. A class would add heap overhead and
an extra pointer dereference.

I don't believe that. How can the pointer dereference have such a
significant cost that it alone determines whether or not whole program is
efficient? If you are really to the point where that is your bottleneck, its
time to drop C# and go to a lower-level language.
 
F

Frank Hileman

?? Every pointer dereference, every instruction, counts in a tight loop. The
lack of user-defined value types in Java (structs in C#) was a deficiency
for high performance applications, both in space (memory) and time. Struct
was added to C# for good reasons.

C# is fine for high performance applications, and we can assume it will get
better over time, especially with regards to structs.

Regards,
Frank Hileman
 
J

Jonathan Allen

?? Every pointer dereference, every instruction, counts in a tight loop

Not true. If the loop isn't the bottleneck in your application, it doesn't
matter what is going on in it.

Honestly, can you think of a single time in your entire life that an extra
dereference in a loop actually made the difference between a usable and
unusable program?

Another consideration is what you are going to do with your N structs. Will
they really live solely in that array? Are you never going to sort it? Are
you never going to return a subset from a function call?

I'm asking because the first time you copy those structs to another
location, you've already lost your gain several times over. Copying a struct
is far more expensive than copying a pointer.
 
B

Brett

Jonathan Allen said:
Not true. If the loop isn't the bottleneck in your application, it doesn't
matter what is going on in it.

Honestly, can you think of a single time in your entire life that an extra
dereference in a loop actually made the difference between a usable and
unusable program?

What do you mean by dereferencing the struct?
Another consideration is what you are going to do with your N structs.
Will they really live solely in that array? Are you never going to sort
it? Are you never going to return a subset from a function call?

What do you mean by returning a subset from a function?
I'm asking because the first time you copy those structs to another
location, you've already lost your gain several times over. Copying a
struct is far more expensive than copying a pointer.

And this is why the class should be used over a struct?

Should a struct ever be used verses a class?
 
F

Frank Hileman

If a loop is not a bottleneck -- why discuss performance? Let us assume the
developer can determine bottlenecks.

Yes, a single pointer dereference has made a critical difference in code I
have written. This type of code is common in graphics libraries, mathematics
libraries, processing huge data sets, scientific applications, collection
libraries, etc.

The increased memory usage of an array of object references (8 bytes heap
overhead per object + 4 bytes per array element pointer) decreases locality
of reference, which also impacts performance. Consider an 8 byte struct.
Substitute a class, and you have increased memory usage by 150%. If you have
an array with 100K elements, the struct version uses 800K bytes, and the
object version uses 2 meg. These types of differences can push you out of a
fast cache limit.

Structs in arrays can be sorted. If a struct is the same size as a pointer,
it is the same cost to copy. If used improperly large structs can be a
problem, but that is no reason to ban mutable structs. A better approach
would be to fix the language, so that a struct copy can be easily
distinguished from a reference (pointer) copy, reducing confusion.

Consider a struct with 8 properties, each internally consuming one byte of
storage. Suppose you need to modify one property. If the struct is
immutable, you must "modify" it by copying all 8 property values to a
constructor for a new struct taking 8 arguments. If the struct is mutable
the code is much simpler -- just change the property. So it is not just a
performance argument.

Frank
 
F

Frank Hileman

Brett said:
What do you mean by dereferencing the struct?

Internally, when you access an array element, if the array element contains
a reference to an object (declared as a class, not a struct) and you access
a field via a property in that object, there are two pointer dereferences:
one to get the address of the array memory block, and one to get the addess
of the field within the object.

By contrast, a struct is stored within the array memory block, so only one
pointer dereference is needed.

We are speaking at the level of the machine code. You cannot see this by
looking at the C# code, except by noticing what type of array you are
working with.

Should a struct ever be used verses a class?

If your abstraction already needs copy-by-value semantics, and it is not too
large, a struct is usually a better choice.

Consider a matrix class that overloads operator*. If you are overloading
operators, you probably want the return value to be a new matrix. In this
case, a struct makes perfect sense if the matrix is not too large and you
will be using lots of operators, as the struct is always passed by value,
and does not have the GC overhead that comes about from creating lots of
small objects.

The other reason for using a struct instead of a class is performance. Again
looking at a graphics package, a Point abstraction will consume less memory
and be faster as a struct, as the Point will typically be used in large
arrays.

We have found that a 6x2 float matrix is a better choice than an equivalent
class. This is larger than the usual choice for a struct, so it was
surprising.


Regards,
Frank Hileman

check out VG.net: http://www.vgdotnet.com
Animated vector graphics system
Integrated Visual Studio .NET graphics editor
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top