views:

329

answers:

5

I'm using auto-implemented properties. I guess the fastest way to fix following is to declare my own backing variable?

public Point Origin { get; set; }

Origin.X = 10; // fails with CS1612

Error Message Cannot modify the return value of 'expression' because it is not a variable

An attempt was made to modify a value type that was the result of an intermediate expression. Because the value is not persisted, the value will be unchanged.

To resolve this error, store the result of the expression in an intermediate value, or use a reference type for the intermediate expression.

A: 

whups indeed Point is a struct thus a value type. No need to new it in the constructor. But to set it you would need to call new. See other better answers ;)

PoweRoy
Point is a struct hence it will exist.
AnthonyWJones
+2  A: 

Using a backing variable won't help. The Point type is a Value type.

You need to assign the whole Point value to the Origin property:-

Origin = new Point(10, Origin.Y);

The problem is that when you access the Origin property what is returned by the get is a copy of the Point structure in the Origin properties auto-created field. Hence your modification of the X field this copy would not affect the underlying field. The compiler detects this and gives you an error since this operation is entirely useless.

Even if you used your own backing variable your get would look like:-

get { return myOrigion; }

You'd still be returning a copy of the Point structure and you'd get the same error.

Hmm... having read your question more carefully perhaps you actually mean to modify the backing variable directly from within your class:-

myOrigin.X = 10;

Yes that would be what you would need.

AnthonyWJones
+11  A: 

This is because Point is a value type (struct).

Because of this, when you access the Origin property you're accessing a copy of the value held by the class, not the value itself as you would with a reference type (class), so if you set the X property on it then you're setting the property on the copy and then discarding it, leaving the original value unchanged. This probably isn't what you intended, which is why the compiler is warning you about it.

If you want to change just the X value, you need to do something like this:

Origin = new Point(10, Origin.Y);
Greg Beech
A: 

I guess the catch here is that you are trying to assign object's subvalues in the statement rather than assigining the object itself. You need to assign the entire Point object in this case as the Prooerty type is Point.

Point newOrigin = new Point(10, 10);
Origin = newOrigin;

Hope I made sense there

MSIL
The important point is that Point is a struct (valuetype). If it was a class (object) then the original code would have worked.
Hans Kesting
Correctamundo - This can be a good interview question.
MSIL
A: 

The problem is that you point to a value located on the stack and the value will not be relfected back to the orignal property so C# does not allow you to return a reference to a value type. I think you can solve this by removing the Origin property and instead use a public filed, yes I know it's not a nice solution. The other solution is to not use the Point, and instead create your own Point type as an object.

Fredrik Normén
If the `Point` is a member of a reference type then it will not be on the stack, it will be on the heap in the containing object's memory.
Greg Beech