访问和更改结构作为属性与作为字段 [英] Accessing and changing structs as property vs as field

查看:30
本文介绍了访问和更改结构作为属性与作为字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Ok, I'll start my question saying that I understand the evil behind mutable structs, but I'm working with SFML.net and using a lot of Vector2f and such structs.

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

What I don't get it is why I can have, and change the values of, a field in a class and can't do the same with a property, in the very same class.

看看这段代码:

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
        }
    }
}

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

note: I'll build my own classes to cover the same functionality and keep with my mutability, but I can't see a technical reason why I can do one and can't do other.

推荐答案

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

When you access a field, you are accessing the actual struct. When you access it through property, you call a method that returns whatever is stored in the property. In the case of a struct, which is a value type, you will get back a copy of the struct. Apparently that copy is not a variable and cannot be changed.

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

Section "1.7 Structs" of the C# language specification 5.0 says:

对于类,两个变量可以引用相同的对象,因此对一个变量的操作可能会影响另一个变量引用的对象.对于结构,变量每个人都有自己的数据副本,这是不可能的一个操作会影响另一个.

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.

这说明您将收到结构的副本,并且无法修改原始结构.但是,它没有说明为什么不允许这样做.

That explains that you will receive a copy of the struct and not be able to modify the original struct. However, it doesn't describe why it isn't allowed.

规范的11.3.3"部分:

Section "11.3.3" of the specifcation:

当结构的属性或索引器是赋值的目标时,与属性或索引器访问相关联的实例表达式必须归类为变量.如果实例表达式是归类为值,则会发生编译时错误.这是描述在 §7.17.1 中进一步详细说明.

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 访问器返回的东西"是一个值而不是一个变量.这解释了错误消息中的措辞.

So the returned "thing" from the get accessor is a value and not a variable. That explains the wording in the error message.

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

The specification also contains an example in section 7.17.1 that is nearly identical to your code:

鉴于声明:

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 是变量.但是,在示例中

the assignments to p.X, p.Y, r.A, and r.B are permitted because p and r are variables. However, in the example

Rectangle r = new Rectangle();
r.A.X = 10;
r.A.Y = 10;
r.B.X = 100;
r.B.Y = 100;

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

the assignments are all invalid, since r.A and r.B are not variables.

这篇关于访问和更改结构作为属性与作为字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆