从属性返回值类型

And*_*ndy 9 c# heap stack properties value-type

我对堆栈和堆中发生的事情与类中的值类型属性相混淆.

到目前为止我的理解:

当您创建具有结构(值类型)的类时,如下所示:

class Foo
{
  private Bar _BarStruct;
  public Bar BarStruct
  {
    get {return _BarStruct; }
    set {_BarStruct = value; }
   }
}

private struct Bar
{
  public int Number;
  Bar()
  {
    Number = 1;
  }
  Bar(int i)
  {
    Number = i;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您创建一个类实例,如下所示:

Foo fooObj = new Foo();
Run Code Online (Sandbox Code Playgroud)

堆栈和堆将如下所示:

https://i962.photobucket.com/albums/ae105/acardy/stackheap-1.jpg(https://i962.photobucket.com/albums/ae105/acardy/stackheap-1.jpg)

...将Bar结构嵌入堆中的Foo类中.这对我来说很有意义,但是当我们考虑在Foo对象中修改BarStruct类中的Number整数时,我开始松开它.例如:

Foo fooObj = new Foo();
fooObj.BarStruct.Number = 1;
Run Code Online (Sandbox Code Playgroud)

据我所知,这应该返回一个BarStruct的副本以存在于堆栈中,这意味着BarStruct成员的任何更改都不会传递给该对象,这就是上面最后一行给出错误的原因.

到目前为止这是对的吗?

如果是这样,我的问题是,如何做出这样的任务:

fooObj.BarStruct = new Bar(2);
Run Code Online (Sandbox Code Playgroud)

...有效并更改堆值?当然这只是改变堆栈上的值?此外,(by和by)我发现它很混乱,你可以在值类型上使用new.对我来说,new是在堆上进行分配(根据C++),并且对堆栈中的项目执行此操作感觉不自然.

所以只是为了重新迭代这个问题,我是否正确地假设当调用包含结构的属性时会发生什么,为什么你可以为副本分配一个新结构但是它仍然会改变堆上的引用?

真的希望这一切都有意义.

如果你需要澄清,请大喊大叫!

钽,

安迪.

Jon*_*eet 10

看看这个作业:

fooObj.BarStruct = new Bar(2);
Run Code Online (Sandbox Code Playgroud)

赋值不会改变堆栈上的值 - 它正在调用属性的setter.

换句话说,你的第一个任务相当于:

fooObj.get_BarStruct().Number = 1; // Bad
Run Code Online (Sandbox Code Playgroud)

第二个相当于:

fooObj.set_BarStruct(new Bar(2));
Run Code Online (Sandbox Code Playgroud)

这有帮助吗?

请注意,如果您将值类型设置为不可变,则有问题的赋值将成为非问题 - 事实上,这通常有帮助.可变值类型在C#中是一个非常糟糕的主意; 你可以忍受它们的麻烦.

就你对"新"的期望而言 - 基本上不要用C++思考.C#不是C++,如果你试图在C#中有效地编写C++,各种各样的事情(析构函数,泛型,构造期间的行为)会让你感到困惑."new"语句创建类型的新实例,无论是值类型还是引用类型.