繁体   English   中英

C#-2个结构问题

[英]C# - 2 struct questions

我知道结构是值类型,但是我不明白为什么这样做:
编辑:我的意思是,为什么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...?
}

第二个问题-我读过,我不需要对结构体使用“ new”,但是没有它对我来说是行不通的。

让我将其分解为几个问题:

什么是变量?

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

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

值类型的变量的值是一个数值 ,并且由复制。 引用类型变量的值是引用,并通过引用复制。 这就是为什么将值类型称为值类型并将引用类型称为引用类型的原因。

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

要更改存储在引用类型的变量中的值,必须先有一个变量。 在这种情况下,您需要执行以下操作:您拥有变量“ a”。 编译器将其编译为“将变量'a'的托管地址传递给带有参数10的Height设置器”。 因此,Height属性设置器知道如何找到存储在'a'中的值的位置并对其进行突变。

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

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

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

是。 故事的寓意是不要使价值类型可变 仅使不可变的值类型。 首先,绝对不要在值类型上使用setter。 只在构造函数中执行赋值。 如果事物必须是可变的,则使其成为引用类型。

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

否。您也可以使用“默认”:

Foo f = default(Foo);

如果Foo是值类型,则它将Foo填充存储位置f的内容,Foo的所有字段均设置为其默认值。

或者,如果值类型是可变的,则可以简单地设置所有字段的值。 但是,如果您不使用构造函数或默认的初始化程序,则必须设置所有它们。 您必须设置所有它们, 包括私有字段

但是,如果一个结构具有所有公共领域,那么这不会以两种方式违反最佳实践准则吗? 首先,因为它具有公共字段,其次,因为它是可变值类型?

是。 不要那样做

我认为您将值类型与不变性混为一谈。 我认为这个SO问题将为您提供帮助。

这很正常。 以及为什么您认为它不能让您为Height设置值? 属性应如何工作是非常正常的行为。 关于调用new ,是的,对于值类型不是必需的。 对于值类型,它仅调用默认构造函数,该构造函数仅使用默认值初始化字段。

“ this.Size.Height = 5”不起作用,因为当将值类型用作属性的类型时,上面的代码行实际上意味着“ this.get_Size()。set_Height(5)”和结果get_Size()调用的是原始副本 ,是值类型。

因此,如果C#允许,将属性值设置为5将会更改副本的值,而不是原始属性值,这是非常不希望的。

当然,当通过局部变量更改类的值类型属性时,这将不适用,因此可以安全地支持此方案。

属性将返回其“ get”方法返回的值。 对于结构和类来说都是一样的。 如果提供“ set”方法,它将执行“ set”指示的所有操作。 无法修改高度的唯一方法是要么使用私有的“集合”,要么根本不提供“集合”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM