C# - 2个结构问题

Pie*_*tro 1 c# struct properties

我知道结构是值类型,但后来我不明白为什么这样有效:
编辑:我的意思是,为什么this.Size.Height不起作用呢?

struct A
{
    int height;

    public int Height
    { 
        get
        {
            return height;
        }

        set
        {
            height = value;
        }
    }
}

//... class Main
{
    A a = A();
    a.Height = 5;  //works. Why? I thought it should say "cannot modify as it is not variable". I think the properties should return copy of this struct...?
}
Run Code Online (Sandbox Code Playgroud)

第二个问题 - 我已经阅读过我不需要使用带有结构的"新"但如果没有它我就无法使用它.

Eri*_*ert 6

让我把它分解为几个问题:

什么是变量?

变量是包含值的存储位置.

为什么值类型称为值类型?

值类型的变量的值是一个数值,并且由复制.引用类型变量的值是引用,并通过引用进行复制.这就是值类型被称为值类型和引用类型被称为引用类型的原因.

为什么a.Height = 10有效?

要更改存储在引用类型变量中的值,您必须有一个变量开头.在这种情况下,您可以:您拥有变量"a".编译器将其编译为"将变量'a'的托管地址传递给具有参数10的高度设置器".因此,Height属性setter知道如何找到存储在'a'中的值的位置并对其进行变异.

为什么a.Size.Height = 10不起作用?

要更改存储在引用类型变量中的值,您必须有一个变量开头.表达"a.Size"不是变量; 这是一个价值.a.Size没有给你支持属性的变量 - 实际上,可能没有.相反,它为您提供了属性的价值.值类型按值复制; 这是属性值的副本.这意味着编译器有两个选择:它可以将值复制到临时变量中然后改变该变量,诱使您认为您已经改变了a.Size的后备存储.或者,它可以给你一个错误,表明你正在做一些愚蠢的事情.它是后者.

这不是令人困惑和烦恼吗?

是.故事的寓意是不要制作可变的价值类型.只制作不可变的值类型.首先不要在值类型上设置setter; 只在构造函数中进行赋值.如果事物必须是可变的,那么将它作为引用类型.

我是否必须使用"new"来创建值类型的新实例?

不.您也可以使用"默认":

Foo f = default(Foo);
Run Code Online (Sandbox Code Playgroud)

如果Foo是值类型,那么这将使用Foo填充存储位置f的内容,Foo将其所有字段设置为其默认值.

或者,如果值类型是可变的,则只需设置所有字段的值即可.但是,如果不使用构造函数或默认初始化程序,则必须设置所有这些.您必须设置所有这些,包括私有字段.

但是,如果某个结构体的所有公共字段都没有以两种方式违反最佳实践指南?首先,因为它有公共字段,第二,因为它是一个可变值类型?

是.不要那样做.