为什么这段代码返回109?

发布于 2025-01-05 01:54:46 字数 833 浏览 0 评论 0原文

有人可以告诉我它是如何工作的吗?我将不胜感激。不知道如何调试这个。

using System;

    class Prg
    {
        private static Func<double, Func<double, double>> Add(int c)
        {
            return x => y => x + y++ + (c *= 2);
        }

        public static void Main(string[] args)
        {
            int a = 1;
            int b = 100;
            var F = Add(2);
            var G = F(a);
            G(b);
            Console.WriteLine(G(b));
        }
    }

编辑:如果您想享受我们的 C# 考试,我还有另一份。这是代码。

delegate int F(); 
class Prg { int a = 10; 
  public F Adder(int x) { 
    int i = x; 
    return delegate { 
      return a += i++; }; 
  } 
  static void Main() { 
    Prg p = new Prg(); 
    F f = p.Adder(5); 
    p.Adder(10); 
    f(); 
    System.Console.Write(f()); 
}  } 

Could someone tell me how does it work? I would be grateful. Dunno how to debug this.

using System;

    class Prg
    {
        private static Func<double, Func<double, double>> Add(int c)
        {
            return x => y => x + y++ + (c *= 2);
        }

        public static void Main(string[] args)
        {
            int a = 1;
            int b = 100;
            var F = Add(2);
            var G = F(a);
            G(b);
            Console.WriteLine(G(b));
        }
    }

EDIT: I have got another one if you want to enjoy our C# exam.. Here is the code.

delegate int F(); 
class Prg { int a = 10; 
  public F Adder(int x) { 
    int i = x; 
    return delegate { 
      return a += i++; }; 
  } 
  static void Main() { 
    Prg p = new Prg(); 
    F f = p.Adder(5); 
    p.Adder(10); 
    f(); 
    System.Console.Write(f()); 
}  } 

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

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

发布评论

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

评论(2

季末如歌 2025-01-12 01:54:47

这部分执行两次:

c *= 2

第一次调用 G(b) 时。第二次打印到控制台时。

一次执行实际上会计算:

a + b++ + (c *= 2)

但由于每次执行时 c 都会乘以 2(并分配回 c),因此您会得到 109 而不是 105。变量 c 被引用为中的一个精确内存位置函数 Add 的范围,实际上用作 Func 委托(并且 Func 的实例始终保持不变),这就是为什么这与使用函数进行一些嵌套调用不同(其中仅传递经过值将出现在函数中,该值将被返回,函数的范围将关闭并且永远不会在相同的上下文中再次访问)。

This part executes twice:

c *= 2

The first time when you call G(b). The second time when you print to console.

One execution actually calculates:

a + b++ + (c *= 2)

But since c gets multiplied by 2 (and assigned back to c) on each execution, you get 109 instead of 105. Variable c is referenced as one exact memory location in the scope of function Add, actually used as Func delegate (and instance of Func remains the same all the time), that's why this is not the same as if you would do some nested calls with functions (where only the transfer by value would occur into the function, the value would be returned, the scope of function closed and never accessed again with the same context).

云朵有点甜 2025-01-12 01:54:46

我首先要说的是:永远不要编写这样的代码。

如果您确实想知道发生了什么:

  1. var F = Add(2) 行中,方法 Add() 创建并返回一个 c==2 的 lambda 表达式。这里重要的是 c 被 lambda 捕获(您可以在 msdn
  2. var G = F(x) 行中,您只需使用参数 a = 1 调用函数,然后您结果得到另一个函数, double -> double 准确地说,
  3. G(b) 行中,您正在调用您的函数,正是这个:x + y++ + (c *= 2); 现在:
    • x 等于 1
    • y 是你的参数,它等于 100
    • c 等于 2,但它被捕获,因此它实际上是对某个已分配字段的引用
    • 这个表达式的结果是 105(100++ 返回 100,2 *= 2 返回 4),所以你得到 1 + 100 + 4 = 105。但是,更重要的是,捕获的变量 c 现在是等于4。y只是一个参数,所以没有改变。
  4. Console.... 行中,您再次调用您的函数。这次,参数再次等于 100,因此结果将相同,但捕获的变量 c 现在等于 4,因此您收到的结果 1 + (100+) + (4 *= 2) -> 1+100+8-> 109

这是一个简短的示例,可以帮助我们了解那里发生的事情:

class Prg
{
    public static void Main(string[] args)
    {
        int captured = 5;
        int param = 3;

        var func = new Func<int, int>(x => x * captured);

        Console.WriteLine(func(param));
        captured = 6;
        Console.WriteLine(func(param));

    }
}

I will start with: don't write such code, ever.

And if you really want to know what is happening:

  1. in line var F = Add(2), method Add() creates and returns a lambda expression with c==2. What is important here, is that c is caught by lambda (you can read about capturing variables on msdn.
  2. In line var G = F(x) you are simply calling your function with parameter a = 1 and you get another function as a result, double -> double to be exact.
  3. In line G(b) you are calling your function, exactly this one: x + y++ + (c *= 2); Now:
    • x is equal to 1
    • y is your parameter, it is equal to 100
    • c is equal to 2, but it is captured, so it is actually a reference to some allocated field
    • Result of this expression is 105 (100++ returns 100, 2 *= 2 returns 4), so you get 1 + 100 + 4 = 105. But, what is more important, variable c, which is captures is now equal to 4. y was just a parameter, so it did not change.
  4. In line Console.... you are invoking your function again. This time, parameter is again equal to 100, so a result would be identical, but your captured variable c is now equal to 4, so a result you receive 1 + (100+) + (4 *= 2) -> 1 + 100 + 8 -> 109

Here's a short example that might shine some light on what has happened there:

class Prg
{
    public static void Main(string[] args)
    {
        int captured = 5;
        int param = 3;

        var func = new Func<int, int>(x => x * captured);

        Console.WriteLine(func(param));
        captured = 6;
        Console.WriteLine(func(param));

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