为何调用Console.WriteLine(foo)时结构体Foo的value值未持续递增?
为何值类型Foo的value在Console.WriteLine(foo)时没有递增?
我知道这看起来很简单,但我就是无法理解原因。以下是相关代码:
static void Main(string[] args) { var foo = new Foo(); Console.WriteLine(foo); Console.WriteLine(foo); object bar = foo; object qux = foo; object baz = bar; Console.WriteLine(baz); Console.WriteLine(bar); Console.WriteLine(baz); Console.WriteLine(qux); } struct Foo { public int value; public override string ToString() { value++; return $"{value}"; } }
这段代码的输出为:1 1 1 2 3 1。我想知道为何执行Console.WriteLine(foo)时变量value的值没有递增。
原因解析
核心问题出在Foo是值类型(struct),值类型的传递逻辑和引用类型完全不同:
调用
Console.WriteLine(foo)时,该方法的参数是object类型,这会触发装箱操作:系统会创建一个新的object实例,把foo的当前值完整复制进去,然后调用这个装箱副本的ToString()方法。也就是说,每次调用Console.WriteLine(foo),修改的都是副本的value,原变量foo的value始终是初始的0,所以两次输出都是1。执行
object bar = foo;时,同样触发装箱操作,把当前foo(value=0)的副本装箱为object实例,bar指向这个实例;object qux = foo;同理,生成另一个独立的装箱副本。而object baz = bar;是引用赋值,因为bar是引用类型(装箱后的object),所以baz和bar指向同一个装箱后的Foo实例。后续的输出调用:
Console.WriteLine(baz):调用共享实例的ToString(),value从0变为1,输出1;Console.WriteLine(bar):同一个实例,value变为2,输出2;Console.WriteLine(baz):同一个实例,value变为3,输出3;Console.WriteLine(qux):调用独立的装箱副本,value从0变为1,输出1。
这就完全对应了代码的输出结果。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

