将静态字段分配给实例字段并不指向同一对象的内容

时间:2015-04-21 05:49:46

标签: c#

In this fiddle,我们正在为实例字段分配静态字段。当我们更改静态值时,实例1仍然具有初始值。这是为什么?我们认为两者都应该指同一个对象,但似乎它们不是。

using System;

public class Program
{
    public static string StaticString;
    public string InstanceString;

    public static void Main()
    {
        Program.StaticString = "foo";

        var p = new Program();
        p.InstanceString = Program.StaticString;

        Program.StaticString = "bar";

        Console.WriteLine(p.InstanceString);
    }
}

我们真的希望打印bar,但打印foo

4 个答案:

答案 0 :(得分:6)

  

在这个小提琴中,我们将静态字段分配给实例字段。

右。这会将静态字段的当前值复制到实例字段。它不会永远将变量绑定在一起 - 只是复制当前值。

  

当我们更改静态实例时,实例一仍然具有初始值。

是的,因为您刚刚更改了静态字段的值 - 为什么 会更改实例字段的值?它们是自变量 - 它们碰巧在一个点上保持相同的值。重要的是,您尚未对实例字段的值所引用的字符串 object 进行任何更改。 (实际上,您无法对字符串对象进行更改,因为字符串是不可变的。)

我将变量视为像纸上写的值一样。当变量是引用类型时,纸上的值只是导航到对象的一种方式 - 就像街道地址一样。但是将一个变量复制到另一个变量总是只是将在一张纸上写的内容复制到另一张纸上。例如,假设我有:

House x = new House();
House y = x;
x.DoorColor = Black;
x = null;
Console.WriteLine(y.DoorColor);

那就像:

  • 创建一张名为x的纸张,并在其上书写街道地址
  • 将写在x张纸上的内容复制到一张名为y
  • 的纸上
  • 去房子,地址写在纸上x并将门涂成黑色
  • 擦掉写在纸上的地址x
  • 去房子,地址写在纸上y并报告门的颜色

最后一步会报告门是黑色的,对吗?撇开纸上x所写的价值并不会改变纸张y上写的内容,也不会改变房子的任何内容。

这与您的代码中的步骤完全相同,但希望它能为它提供更多亮点......

答案 1 :(得分:2)

在下面的语句中将StaticString分配给实例字符串

p.InstanceString = Program.StaticString;

运行时实际上会将InstanceString指向字符串" foo"不要StaticString所以当你分配StaticString值栏时,运行时会创建一个字符串" bar"并将静态字符串指向它。注意实例字符串仍然指向我们有foo的内存位置。

我认为借助图表可以更容易理解。这表明StaticString和InstanceString实际上是如何指向值的。

enter image description here

答案 2 :(得分:1)

在设置为p.InstanceString之前打印foo两行。所以它应该打印foo

答案 3 :(得分:0)

我很难改变变量的并改变参考点所指向的对象

字符串不可变的事实当然使问题复杂化。 b = "foo"b = new string("foo".ToCharArray())完全相同。我们正在创建一个新对象并将其引用分配给b 。我们不会改变现有的对象。

Here is an example that clarifies my mistake.

using System;
using System.Text;

public class Program
{
    public static StringBuilder StaticString;
    public StringBuilder InstanceString;

    public static void Main()
    {
        Program.StaticString = new StringBuilder("foo");

        var p = new Program();
        p.InstanceString = Program.StaticString;

        Console.WriteLine("Mutating the object at which a value points:");
        Program.StaticString.Append("bar");
        Console.WriteLine(p.InstanceString);
        Console.WriteLine(Program.StaticString);

        Console.WriteLine("\nChanging the value of a variable:");
        Program.StaticString = new StringBuilder("raboof");
        Console.WriteLine(p.InstanceString);
        Console.WriteLine(Program.StaticString);
    }
}

输出

Mutating the object at which a value points:
foobar
foobar

Changing the value of a variable:
foobar
raboof