从属性返回值类型

发布于 2024-08-16 22:09:35 字数 1306 浏览 8 评论 0原文

我对类中的值类型属性在堆栈和堆上发生的情况感到困惑。

到目前为止我的理解:

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

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++),对堆栈上的项目执行此操作感觉不自然。

因此,只是重申一下这个问题,我对调用包含结构的属性时会发生什么的假设是否正确?为什么可以将新结构分配给副本,但它仍然会更改堆上的引用?

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

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

塔,

安迪。

I'm getting confused with what happens on the stack and heap in respect to value type properties in classes.

My understanding so far:

When you create a class with a structure (value type) like this:

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

If you create a class instance like so:

Foo fooObj = new Foo();

The stack and heap will look like this:

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

...where the Bar structure is embeded in the Foo class in the heap. This makes sense to me, but I start to loose it when we consider modifying the Number integer in the BarStruct class, within the Foo Object. For example:

Foo fooObj = new Foo();
fooObj.BarStruct.Number = 1;

As I understand, this should be returning a copy of BarStruct to live on the stack, which means that any changes of a member of BarStruct would not be carried through to the object, which is why the last line above gives an error.

Is this right so far?

If so, my question is, how come an assignment such as this:

fooObj.BarStruct = new Bar(2);

...is valid and changes the heap value? Surely this is just changing the value on the stack?? Also, (by and by) I find it so confusing that you are able to use new on a value type. To me, new is for allocatting on the heap (as per C++) and feels unnatural to be doing this for items on the stack.

So just to re-iterate the question, Am I correct in my assumption of what happens when a property containing a structure is called and why can you assign a new structure to a copy and yet it still changes the reference on the heap?

Really hope this all make sense.

Yell if you need clarification!

Ta,

Andy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

勿挽旧人 2024-08-23 22:09:35

查看此赋值:

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”语句创建类型的新实例,无论该类型是值类型还是引用类型。

Looking at this assignment:

fooObj.BarStruct = new Bar(2);

The assignment isn't changing the value on the stack - it's calling the setter for the property.

In other words, whereas your first assignment is equivalent to:

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

the second is equivalent to:

fooObj.set_BarStruct(new Bar(2));

Does that help?

Note that the problematic assignment becomes a non-issue if you make your value type immutable to start with - which helps in general, in fact. Mutable value types are a really bad idea in C#; you can get into no end of trouble with them.

In terms of your expectations of "new" - try not to think in C++, basically. C# isn't C++, and various things (destructors, generics, behaviour during construction) will confuse you if you try to effectively write C++ in C#. A "new" statement creates a new instance of a type, whether that's a value type or a reference type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文