C# Struct method doesn't save value if accessed by a property
I need to create a structure that looks like an int (but has an extra field that I need...), so I created a new structure named TestStruct added one method (test()) that I needed and overloaded some operators, and it seemed to be working well...
The sample below shows the problem. If the structure test() method is executed from the Val property then the Val property seems to lose the value, but if the method is executed on the Val2 variable, this one seems to keep the right value...
Why does this happen?
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
new TestClass();
}
}
public class TestClass
{
public TestStruct Val { get; set; }
private TestStruct Val2;
public TestClass()
{
Val.test();开发者_StackOverflow社区
Console.WriteLine(Val + "-> why is it not 10?");
//Direct assignment works well...
Val = 123;
Console.WriteLine(Val + "-> direct assingment works..");
//This way works too. Why doesn't it work with "get;" and "set;"?
Val2.test();
Console.WriteLine(Val2 + "-> it works this way");
}
}
public struct TestStruct
{
private Int32 _Value;
public long Offset { get; set; }
public static implicit operator TestStruct(Int32 value)
{
return new TestStruct { _Value = value };
}
public static implicit operator Int32(TestStruct value)
{
return value._Value;
}
public void test()
{
_Value = 10;
}
}
Your struct
is wrong.
For a very large number of reasons, you should never make a mutable struct.
Just like an int
or DateTime
value is immutable and can never change, so too a specific value of your struct
must never change at all.
Instead, you can make functions that return a new, different value .
Here are some reasons that mutable structs are evil:
- http://ericlippert.com/2008/05/14/mutating-readonly-structs/
- http://blog.slaks.net/2010/12/when-shouldnt-you-write-ref-this.html
- http://codeblog.jonskeet.uk/2010/07/27/iterate-damn-you/
- http://philosopherdeveloper.wordpress.com/2011/03/31/how-i-discovered-a-bug-in-the-c-compiler-part-1/
To answer the question, Val.test()
is equivalent to get_Val().test()
.
Since structs are value types, `get_Val() (the automatically-generated property getter) returns a copy of the struct.
The original struct in the private backing field is not affected.
It's a struct, so it's a value type - it's copied by value, not by reference.
Properties are just syntactic sugar around method calls, Val compiles down to this:
private TestStruct _valBackingField;
public TestStruct get_Val {
return _valBackingField;
}
When accessing a struct through a property, you are getting a fresh copy every time you access the Getter. When accessing a struct through a field, you are getting the same object every time.
That's why mutable value types are considered evil™.
When you use Val, the property is returning a copy , it's that copy you modify, then you access the property again which gets another copy.
If you change the struct to a class this problem should go away because if the difference in how classes and structs are treated.
After reading some links, I understand the problem..
I've fix it by changing the test()
method to return a new structure with the new value and then instead of doing Val.test()
I do Val = Val.test();
.
I think a similar situation occurs when we want to replace some chars in a string, we must do something like str = str.replace("xx","yy");
Thank you all for helping me out. I didn't expect to get all those replies so quickly
精彩评论