Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#-2结构问题_C#_Properties_Struct - Fatal编程技术网

C#-2结构问题

C#-2结构问题,c#,properties,struct,C#,Properties,Struct,我知道结构是值类型,但我不明白为什么这样做: 编辑:我的意思是,为什么这个.Size.Height不起作用? struct A { int height; public int Height { get { return height; } set { height = value; } } } //... cla

我知道结构是值类型,但我不明白为什么这样做:
编辑:我的意思是,为什么这个.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”,但如果没有它,它对我来说是不起作用的

我认为您混淆了值类型和不变性。我认为这会对您有所帮助。

我认为您混淆了值类型和不变性。我想这会对你有帮助。

这很正常。为什么你们认为它不能让你们设定高度值? 属性如何工作是非常正常的行为。
关于调用
new
,是的,对于值类型,它不是强制性的。对于值类型,它只调用默认构造函数,该构造函数只使用默认值初始化字段。

这很正常。为什么你们认为它不能让你们设定高度值? 属性如何工作是非常正常的行为。
关于调用
new
,是的,对于值类型,它不是强制性的。对于值类型,它只调用默认构造函数,默认构造函数只使用默认值初始化字段。

属性将返回其“get”方法返回的值。结构和类也是如此。如果您提供一个“set”方法,它将执行“set”指示的任何操作。无法修改高度的唯一方法是使用私有“set”,或者根本不提供“set”。

属性将返回其“get”方法返回的值。结构和类也是如此。如果您提供一个“set”方法,它将执行“set”指示的任何操作。无法修改高度的唯一方法是使用私有“set”,或者根本不提供“set”。

“this.Size.Height=5”不起作用,因为当值类型用作属性类型时,上面的代码行实际上意味着“this.get\u Size().set\u Height(5)”,以及get\u Size()的结果调用是原始的副本,是值类型

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

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

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

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


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

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

什么是变量

变量是包含值的存储位置

为什么值类型被称为值类型

值类型的变量的值是值,并按值复制。引用类型的变量的值是引用,并通过引用进行复制。这就是为什么值类型称为值类型,引用类型称为引用类型

为什么a.高度=10起作用

要更改存储在引用类型变量中的值,首先必须有一个变量。在本例中,您需要:您有变量“a”。编译器将其编译为“将变量“a”的托管地址与参数10一起传递给高度设置器”。因此,Height属性设置器知道如何找到存储在“a”中的值的位置并对其进行变异

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

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

这难道不令人困惑和烦恼吗

对。这个故事的寓意是不要制造可变的价值类型。只生成不可变的值类型。从一开始就不要在值类型上设置setter;仅在构造函数中执行赋值。如果该对象必须是可变的,则将其设置为引用类型

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

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

如果Foo是一种值类型,那么它将用Foo填充存储位置f的内容,Foo的所有字段都设置为默认值

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

但是,如果一个结构拥有所有公共字段,这是否在两个方面违反了最佳实践指南?第一,因为它有公共字段,第二,因为它是可变值类型


对。不要那样做。

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

什么是变量

变量是包含值的存储位置

为什么值类型被称为值类型

值类型的变量的值是值,并按值复制。引用类型的变量的值是引用,并通过引用进行复制。这就是为什么值类型被称为值类型,而引用类型被称为
Foo f = default(Foo);