类中的属性作为值类型

huangapple go评论71阅读模式
英文:

ValueType as property in class

问题

我对类中值类型属性的概念有点困惑。
据我理解,当调用getter时,会返回值类型的副本。
让我们来看一个例子:

public struct Point
{
    public int X;
    public int Y;

    public void Set(int x, int y)
    {
        X = x;
        Y = y;
    }
}

public class Test
{
    public Int32 X { get; set; }

    public void SetX(int x) => X = x;

    public Point Point { get; set; }
}

static void Main(string[] args)
{
    var test = new Test();
    test.SetX(10);
    test.Point.Set(20, 30);

    Console.WriteLine(test.X);
    Console.WriteLine($"{test.Point.X} {test.Point.Y}");
}

Point 没有被修改,因为它是值类型,getter 返回给我们一个副本,这是有道理的。我不明白的是,为什么在这种情况下 X 被修改?它也是一个值类型。这对我来说看起来有矛盾之处。
请帮助我理解我漏掉了什么。

英文:

I am a bit confused with a concept of value types as properties in a class.
As far as I understand, when getter is called - a copy of value type is returned.
Let's have an example:

public struct Point
{
    public int X;
    public int Y;

    public void Set(int x, int y)
    {
        X = x;
        Y = y;
    }
}

public class Test
{
    public Int32 X { get; set; }

    public void SetX(int x) => X = x;

    public Point Point { get; set; }
}

static void Main(string[] args)
{
    var test = new Test();
    test.SetX(10);
    test.Point.Set(20, 30);

    Console.WriteLine(test.X);
    Console.WriteLine($"{test.Point.X} {test.Point.Y}");
}

Point is not modified, since it is a value type, and getter gives us a copy, which makes sense. The thing I don't understand - why in this case X is modified? It is a value type also. This looks like a contradiction to me.
Please help me to understand what I am missing

答案1

得分: 2

Point is not modified, since it is a value type, and getter gives us a copy, which makes sense

这里 Point 没有被修改,因为它是一个值类型,而 getter 给了我们一个副本,这是有道理的。

The thing I don't understand - why in this case X is modified?

我不明白的是 - 为什么在这种情况下 X 被修改了?

Because you are modifying object containing X not the copy of X. X = x invokes setter (there is no "returns copy" happening here) for auto-property which will write corresponding value to corresponding memory location.

因为你正在修改包含 X 的对象,而不是 X 的副本。X = x 调用了setter(这里没有发生“返回副本”),对于自动属性,它会将相应的值写入相应的内存位置。

Code for Point simulating this behavior can look for example like:

模拟这种行为的 Point 代码可以如下所示:

public void SetPoint(int x, int y) => Point = new Point{X= x, Y =y};

And in both cases the following will work:

而在两种情况下,以下代码都会起作用:

test.X = 42;
test.Point = new Point {X = 7, Y = 42}

演示 @sharplab.io

英文:

> Point is not modified, since it is a value type, and getter gives us a copy, which makes sense

Yes, because you get a make changes to local copy of Point returned by auto-property getter.

> The thing I don't understand - why in this case X is modified?

Because you are modifying object containing X not the copy of X. X = x invokes setter (there is no "returns copy" happening here) for auto-property which will write corresponding value to corresponding memory location.

Code for Point simulating this behavior can look for example like:

public void SetPoint(int x, int y) => Point = new Point{X= x, Y =y};

And in both cases the following will work:

test.X = 42;
test.Point = new Point {X = 7, Y = 42}

Demo @sharplab.io

答案2

得分: 0

修改 'Test.Point' 代码如下:
    static void Main(string[] args)
    {
        var test = new Test();
        test.SetX(10); // 你给属性赋了一个新值
        // test.Point.Set(20, 30); - 你改变了一个值的副本,没有将结果分配给属性  
        test.Point = new Point(){ X = 20, Y = 30 }

        Console.WriteLine(test.X);
        Console.WriteLine($"{test.Point.X} {test.Point.Y}");
    }
在值类型中,结构体只能拥有(用户定义的)属性或方法来修改自身。这让人感到困惑。你可以遵循建议,使用只读结构体以避免出现难以识别的行为可能性。
英文:

To modify 'Test.Point' code this:

        static void Main(string[] args)
        {
            var test = new Test();
            test.SetX(10); // you assign a new value to the property
            // test.Point.Set(20, 30); - you change a copy of the value without assignment of the result to the property  
            test.Point = new Point(){ X = 20, Y = 30 }

            Console.WriteLine(test.X);
            Console.WriteLine($"{test.Point.X} {test.Point.Y}");
        }

Among ValueTypes the struct only can have (user defined) properties or methods which can modify itself. It confuses a lot. You can follow recommendation to use the read-only structs to avoid any possibility of such behavior which is hard to identify.

huangapple
  • 本文由 发表于 2023年7月27日 23:14:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76781169.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定