c# - 访问和更改结构作为属性与作为字段

标签 c# struct

好的,我将开始我的问题,说我了解可变结构背后的邪恶,但我正在使用 SFML.net 并使用大量 Vector2f 和此类结构。

我不明白的是为什么我可以拥有并更改类中的字段的值,而不能对同一个类中的属性执行相同操作。

看看这段代码:

using System;

namespace Test
{
    public struct TestStruct
    {
        public string Value;
    }

    class Program
    {
        TestStruct structA;
        TestStruct structB { get; set; }

        static void Main(string[] args)
        {
            Program program = new Program();

            // This Works
            program.structA.Value = "Test A";

            // This fails with the following error:
            // Cannot modify the return value of 'Test.Program.structB'
            // because it is not a variable
            //program.structB.Value = "Test B"; 

            TestStruct copy = program.structB;
            copy.Value = "Test B";

            Console.WriteLine(program.structA.Value); // "Test A"
            Console.WriteLine(program.structB.Value); // Empty, as expected
        }
    }
}

注意:我将构建自己的类来覆盖相同的功能并保持我的可变性,但我看不出为什么我可以做一个而不能做其他的技术原因。

最佳答案

当您访问一个字段时,您正在访问实际的结构。当您通过属性访问它时,您调用了一个方法,该方法返回存储在属性中的任何内容。在结构体是值类型的情况下,您将获得该结构体的副本。显然,该副本不是变量,无法更改。

C# 语言规范 5.0 的“1.7 结构”部分说:

With classes, it is possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. With structs, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other.



这解释了您将收到结构的副本并且无法修改原始结构。但是,它没有描述为什么不允许这样做。

规范的“11.3.3”部分:

When a property or indexer of a struct is the target of an assignment, the instance expression associated with the property or indexer access must be classified as a variable. If the instance expression is classified as a value, a compile-time error occurs. This is described in further detail in §7.17.1.



所以从 get 访问器返回的“东西”是一个值而不是一个变量。这解释了错误消息中的措辞。

该规范还在第 7.17.1 节中包含一个与您的代码几乎相同的示例:

鉴于声明:
struct Point
{
    int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int X {
        get { return x; }
        set { x = value; }
    }
    public int Y {
        get { return y; }
        set { y = value; }
    }
}
struct Rectangle
{
    Point a, b;
    public Rectangle(Point a, Point b) {
        this.a = a;
        this.b = b;
    }
    public Point A {
        get { return a; }
        set { a = value; }
    }
    public Point B {
        get { return b; }
        set { b = value; }
    }
}

在示例中
Point p = new Point();
p.X = 100;
p.Y = 100;
Rectangle r = new Rectangle();
r.A = new Point(10, 10);
r.B = p;

允许对 p.X、p.Y、r.A 和 r.B 进行赋值,因为 p 和 r 是变量。但是,在示例中
Rectangle r = new Rectangle();
r.A.X = 10;
r.A.Y = 10;
r.B.X = 100;
r.B.Y = 100;

赋值都是无效的,因为 r.A 和 r.B 不是变量。

关于c# - 访问和更改结构作为属性与作为字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18292087/

相关文章:

c# - 绑定(bind)到 UserControl 的依赖属性

c# - 错误 CS1022 : Type or namespace definition, 或预期的文件结尾

c - 如何执行结构的指针变量的内存设置,该结构是 C 中另一个结构的指针变量

c# - DataGridViewColumn 索引在数据清除后发生变化

c# - 哪个数据集行违反了数据库唯一约束?

go - 从数据 golang slice 初始化创建 Struct 实例

c - 在结构不是全局的情况下访问结构

C 指向另一个结构体的指针

c# - 我可以发布私有(private) NuGet 包吗?

go - 如何使用 pgx 将 QueryRow 扫描到结构中