繁体   English   中英

从属性返回值类型

[英]Returning a value type from a property

关于类中的值类型属性,我对堆栈和堆上发生的事情感到困惑。

到目前为止我的理解:

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

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

如果你像这样创建一个类实例:

Foo fooObj = new Foo();

堆栈和堆将如下所示:

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;

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

到目前为止,这是正确的吗?

如果是这样,我的问题是,怎么会有这样的作业:

fooObj.BarStruct = new Bar(2);

...有效并更改堆值? 当然这只是改变堆栈上的值?? 此外,(渐渐地)我发现它非常令人困惑,以至于您可以在值类型上使用 new 。 对我来说,new 用于在堆上分配(按照 C++),并且为堆栈上的项目执行此操作感觉不自然。

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

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

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

塔,

安迪。

看看这个作业:

fooObj.BarStruct = new Bar(2);

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

换句话说,而您的第一个作业相当于:

fooObj.get_BarStruct().Number = 1; // Bad

第二个相当于:

fooObj.set_BarStruct(new Bar(2));

这有帮助吗?

请注意,如果您使值类型一开始不可变,则有问题的分配将成为非问题 - 事实上,这通常有帮助。 可变值类型在 C# 中是一个非常糟糕的主意; 你可能会遇到无穷无尽的麻烦。

就您对“新”的期望而言 - 基本上尽量不要用 C++ 思考。 C# 不是 C++,如果您尝试在 C# 中有效地编写 C++,那么各种事情(析构函数、泛型、构造期间的行为)会让您感到困惑。 “new”语句创建一个类型的新实例,无论是值类型还是引用类型。

暂无
暂无

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

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