幕后发生了什么,因此代码返回1而不是43?

时间:2018-08-24 19:08:23

标签: c#

在一本书中发现了这一点,但是解释太短了。

public class Program
{
    int a = 0;

    private static void Main()
    {
        var val = new Program();
        val.a += val.Foo();

        Console.WriteLine(val.a);
        Console.ReadKey();
    }
    private int Foo()
    {
        a = a + 42;
        return 1;
    }
}

是否需要对拳击做一些事情?

3 个答案:

答案 0 :(得分:5)

这与拳击无关,这是操作顺序...

class Program
{
    int a = 0;

    static void Main()
    {
        Program val = new Program();
        val.a += val.Foo();
        Console.WriteLine(val.a);

        Console.ReadKey();
    }

    int Foo()
    {
        a = a + 42;
        return 1;
    }
}

所以发生了什么

val.a += val.Foo();

基本上被重写为

val.a = val.a + val.Foo();

由于操作的顺序,这就是要压入堆栈的内容:

val.a = 0
val.Foo = 1

因此,当val.a += val.Foo()的求值开始时,它将保存val.a的当前值为零,然后调用该函数。该函数会修改val.a,但是由于它是一个值类型,因此它不会更新原始调用方中保存的值。 val.Foo()返回后,等式变为val.a = 0 + 1,因此结果为1,而不是43

如果将其稍作重写,则会得到不同的结果:

val.a = val.Foo() + val.a;

然后将得到43。这是一个操作顺序问题。

答案 1 :(得分:3)

让我们看看:

 // val.a = 0
 Program val = new Program(); 
 // val.a += val.Foo()           can be rewritten as 
 // val.a = val.a + val.Foo()    or initial value of val.a + result of val.Foo()
 // val.a = 0 + 1 
 val.a += val.Foo();  
 // print out 1 
 Console.WriteLine(val.a);   

编辑::如果您想利用副作用(在a方法中将42分配给Foo()),可以放置(而不是val.a = val.a + val.Foo()):

 // result of val.Foo + current val.a value 
 // 1 + 42 == 43
 val.a = val.Foo() + val.a;

答案 2 :(得分:-1)

Foo()上,您始终返回1。

正确的代码:

int Foo()
{
    a = a + 42;
    return a;
}