Can't modify non-variable compiler bug

  • Thread starter Thread starter Alexander Arlievsky
  • Start date Start date
A

Alexander Arlievsky

Hi,
C# compiler issues error message on the following lines:
GetStruct().Depth = 10;
if GetStruct() returns structure (value type). It seems to be correct - else
you will modify temporary value on the stack.
It still allows to call method, so GetStruct().SetDepth(10) compiles
perfectly, although obviosly still modifies only temporary value on the
stack.
But in our case "Depth" is property, and its "set" implementation modifies
some external object - our structure is just wrapper around
reference to other object. We made this wrapper value type to prevent
excessive memory allocations for each GetStruct() call.
So in our case it makes sense to write GetStruct().SetDepth(10) - it
modifies non-temporary object,
and if you write on the next line Assert(GetStruct().Depth == 10) -
assertion isn't failed.

It looks like compiler should threat property call here as method call, not
as simple field assignment.

Any ideas ?

Alexander Arlievsky
C.T.O. mPrest Ltd.
(e-mail address removed)
 
Alexander,

I don't quite understand why you don't use a reference type for this.
In doing something like this:

// Set the value on the structure.
GetStruct().Depth = 10;

You are actually allocating the memory on the stack for the structure.
Then, you are boxing the structure. The reason the structure is boxed (a
new object instance is created on the heap anyways) is because you are doing
a property access, and not a simple field access.

I would make your type that is returned a reference type, since you are
going to have to allocate memory on the heap regardless of whether or not
you use a value type or reference type.

Hope this helps.
 
Nicholas,
// Set the value on the structure.
GetStruct().Depth = 10;

You are actually allocating the memory on the stack for the structure.
Then, you are boxing the structure. The reason the structure is boxed (a
new object instance is created on the heap anyways) is because you are doing
a property access, and not a simple field access.

I don't see any reason for the structure to be boxed. Calling methods on
value types doesn't cause any boxing even (at least with c#) if the method
is virtual.
Alexander is right. This won't allocate anything on the heap.
The problem is (IMHO) that the value types are ment to be used to hold
values and not references. Keeping references as a members of value types is
error prone. Anyway, it's legal.
Hence reporting GetStruct().Depth = 10 as an error is overkill. It should've
been reported as warning instead. Had the compiler reported those cases as
warnings we would've had some way to suppress that warnings as well. Like
*new* keyword when hiding inherited methods.

Anyway, to go arround this the following can be used:
WrapperStruct ws = GetStruct();
ws.Depth() = 10;
This won't use more memory we just gave name of the returned value. This
will make the compiler happy because if we want to we can use the new value
of the property.
 
Alexander,

I don't quite understand why you don't use a reference type for this.
In doing something like this:

// Set the value on the structure.
GetStruct().Depth = 10;

You are actually allocating the memory on the stack for the structure.
Then, you are boxing the structure. The reason the structure is boxed (a
new object instance is created on the heap anyways) is because you are doing
a property access, and not a simple field access.

I would make your type that is returned a reference type, since you are
going to have to allocate memory on the heap regardless of whether or not
you use a value type or reference type.

What do you mean by that? i.e. enclose the struct in a class proxy?
I fooled around with this a little, and could not figure a way to make
GetStruct() return a reference without resorting to unsafe and
pointers...is there some syntax to do that directly?
 
Back
Top