代码之家  ›  专栏  ›  技术社区  ›  GurdeepS

使用action时int递增的奇怪行为

c#
  •  1
  • GurdeepS  · 技术社区  · 14 年前

    给出以下代码:

    class Sample
    {
     public static void Run()
     {
         int i = 1;
         Action<int> change = Increment();
         for (int x = 0; x < 5; x++ )
         {
             change(i);
             Console.WriteLine("value=" + i.ToString());
         }
     }
    
     public static Action<int> Increment()
     {
          return delegate(int i) { i++; };
     }
    

    }

    我得到答案:

    值=1 值=1 值=1 值=1 值=1 值=1

    而不是1,2,3…6。

    这是网上一篇文章的线索,但我不明白为什么。有人有什么想法吗?

    3 回复  |  直到 14 年前
        1
  •  6
  •   SLaks    14 年前

    正在按值传递参数。

    写作 i++ 将更改的值 i 不同的 int 值(与可变类型不同)。
    当你写作时 i++ 在委托中,将参数更改为 int 价值。但是,这不会影响其值已复制到参数的局部变量。

    要解决此问题,您需要使用 ref 参数。 裁判 参数通过引用传递。因此,当你改变一个 ref int 不同的参数 int 值时,还将更改本地变量或字段 参考 作为参数传递。

    有关详细信息,请参见 here .

    自从 Action 代表不接受 裁判 参数,则需要创建自己的委托类型,如下所示:

    delegate void RefAction<T>(ref T param);
    
        2
  •  6
  •   Kasper Holdum    14 年前

    数据类型 int 是基元数据类型,因此是值类型,而不是引用类型。这意味着当传递变量时 传递给函数的不是实际变量,而是值的副本。因此,当参数在函数内部更改时,它是已更改的本地副本,而不是原始变量。

    如果您确定希望函数能够修改原始变量的值,则应添加 裁判 函数参数签名的关键字,以告诉编译器要将变量作为引用传递。

    public void ChangeOriginal(ref int something)
    { something = something + 1;}
    
    public void ChangeLocalCopy(int something)
    {something = something + 1;}
    

    我建议你读一下 stack vs the heap (值类型vs引用类型)因为它是编程时非常基本的主题。

        3
  •  2
  •   Preet Sangha    14 年前

    操作不返回任何内容。它只会增加传入的值,而不是对原始值的引用(正如slaks所说)。你可以用func这样做。

    class Sample
    {
     public static void Run()
     {
         int i = 1;
         Func<int, int> change = Increment();
         for (int x = 0; x < 5; x++ )
         {
             i = change(i);
             Console.WriteLine("value=" + i.ToString());
         }
     }
    
     public static Func<int, int> Increment()
     {
          return delegate(int i) { return ++i; };
     }
    }