C# Struct method doesn't save value if accessed by a property

喜欢而已 提交于 2019-11-26 21:42:45

问题


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();
        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;
    }
}

回答1:


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:

  1. http://ericlippert.com/2008/05/14/mutating-readonly-structs/
  2. http://blog.slaks.net/2010/12/when-shouldnt-you-write-ref-this.html
  3. http://codeblog.jonskeet.uk/2010/07/27/iterate-damn-you/
  4. 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.




回答2:


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™.




回答3:


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.




回答4:


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



来源:https://stackoverflow.com/questions/6770604/c-sharp-struct-method-doesnt-save-value-if-accessed-by-a-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!