值类型字段是引用类型?

时间:2017-02-13 17:14:38

标签: c# stack value-type

我在这里有点困惑。对于结构体,我无法直接更改其字段,因为整个结构都是值类型。 但是具有值类型字段的类呢?如果我有一个公共字段int X,我可以正确修改它。因此,其领域的价值类型性质的唯一表现是,当作为论证传递时,它是一个副本?

编辑:还

Class A
{
  int B=100;  //this is a field, so reference type. But it is a value type.
}

B的内容地址存储在堆上,但是存储在堆栈中的B的值是多少?

3 个答案:

答案 0 :(得分:1)

  

对于结构体,我无法直接更改其字段,因为整个结构都是值类型。

当C#为您复制struct时,您无法更改字段。在其他情况下,您可以修改struct的字段。以下是差异的小例子:

struct Foo {
    public int A {get;set;}
    public void SetA(int a) {
        A = a;
    }
}

class Bar {
    Foo f;
    public Foo F {
        get{return f;}
        set {f = value;}
    }
    public void SetFooA(int x) {
        f.SetA(x);
    }
}

public static void Main() {
    Bar b = new Bar();
    b.F.SetA(123);  // b.F makes a copy, so changing A fails
    Console.WriteLine("{0}", b.F.A);
    b.SetFooA(456); // Inside Bar, f.SetA is called directly, so the change works fine
    Console.WriteLine("{0}", b.F.A);
    b.F = new Foo { A = 112233 }; // This also works, because the whole F is assigned
    Console.WriteLine("{0}", b.F.A);
}
  

如果我有公共字段int X,我可以正确修改它。

同样的规则适用于用户定义的struct,只要您修改它的全部内容即可。您无法修改int的部分内容,因为它不是复合内容。当您一次分配整个struct时,struct的修改可以正常工作。换句话说,分配

b.F = new Foo { A = 112233 };
我的示例中的

替换了分配

B = 100;

在你的例子中。

Demo.

答案 1 :(得分:0)

  

B的内容地址存储在堆上,但是存储在堆栈中的B的值是多少?

没有。类的值类型字段存储在堆上。

有关详细信息,请参阅@Marc Gravell的答案:

Why value-types are stored onto Stacks?

您可能还想阅读@Eric Lippert关于此主题的博文:https://blogs.msdn.microsoft.com/ericlippert/2010/09/30/the-truth-about-value-types/

在短值类型中,可以存储在堆栈中,但它们并不总是存储在堆栈中。

答案 2 :(得分:-1)

Struct为您提供原始字段的副本,因为将传递结构的副本。将它更改为类会传递对类的引用,因此如果要更改它,该字段将会修改。