简体   繁体   English

为什么我的INT变量通过引用传递? C#

[英]Why is my INT variable being passed by reference?? C#

Ok so I know the difference (I think) between value types and reference types in C#. 好的,我知道C#中的值类型和引用类型之间的区别(我认为)。 However, the code below does not behave the way I would expect knowing what I know about value types and reference types. 但是,下面的代码无法像我期望的那样了解我对值类型和引用类型的了解。

delegate void SomeHandler();

static Action GetSomeHandler()
 {
   int x = 1;

   SomeHandler a = delegate { Console.WriteLine(x); };

   x = 2;

   return a;
 }

static void Main(string[] args)
{
   SomeHandler a = GetSomeHandler();

   a();
}

I'm confused because a local variable "x" is declared and initialized to 1 inside my GetSomeHandler method. 我很困惑,因为在我的GetSomeHandler方法中声明了局部变量“ x”并将其初始化为1。 Then, a new delegate "a" of type SomeHandler is declared and assigned to an anonymous method that writes "x" to the console. 然后,声明一个SomeHandler类型的新委托“ a”并将其分配给将“ x”写入控制台的匿名方法。 "x" is then assigned to 2. Finally, "a" is invoked and the value of "x" is printed to the console. 然后将“ x”分配给2。最后,调用“ a”并将“ x”的值打印到控制台。

I expected the output to be 1 because "x" is an int (a value type) and I would assume that when 2 was assigned to "x" it would not affect what I have used in my delegate because the value would be copied and not pointed to the same location in memory but the actual output is 2!! 我期望输出为1,因为“ x”是一个int(值类型),并且我假设当2被分配给“ x”时,它不会影响我在委托中使用的内容,因为该值将被复制并没有指向内存中的相同位置,但实际输出为2! WHY!? 为什么!?

Ah, you have discovered the magic of closures ! 啊,您发现了关闭的魔力!

You are correct in thinking that "x" is a value type and that it should not behave in this way; 您认为“ x”是值类型并且不应以这种方式运行是正确的。 that is if you weren't declaring an anonymous function inside of your method. 也就是说,如果您未在方法内部声明匿名函数。 An anonymous method is a closure and is bound to its parenting method body and the local variables in it (In this case it is the local variable "x" and the parenting method GetSomeHandler). 匿名方法是一个闭包,并绑定到其父方法主体和其中的局部变量(在本例中为局部变量“ x”和父方法GetSomeHandler)。

The important distinction is that it is bound to variables , not to values . 重要的区别是它与变量绑定,而不是 In other words, the value of "x" is not copied in when "a" is declared. 换句话说,声明“ a”时不会复制“ x”的值。 Instead, a "reference" to "x" is used so that "a" will always use the most recent value of "x". 而是使用对“ x”的“引用”,以便“ a”将始终使用“ x”的最新值。 In fact, this "reference" to "x" will be persisted even if "x" goes out of scope. 实际上,即使“ x”超出范围,对“ x”的这种“引用”也将保留。 When you compile your program the compiler then works some of its "compiler magic" and generates something similar to the following snippet of code: 编译程序时,编译器随后会发挥其“编译器魔力”,并生成类似于以下代码片段的内容:

delegate void SomeHandler();

// This is the helper class generated by the compiler that allows an anonymous function inside your method access to local variables even after the function or method has returned.
sealed class SomeHandlerClosure
{
   public int x;

   public void CompilerNamedMethod()
   {
     Console.WriteLine(x);
   }
}

static SomeHandler GetSomeHandler()
 {
   SomeHandlerClosure closure = new SomeHandlerClosure();
   closure.x = 1;

   SomeHandler a = new SomeHandler(closure.CompilerNamedMethod);

   closure.x = 2;

   return a;
 }

static void Main(string[] args)
 {
   SomeHandler a = GetSomeHandler();

   a();
 }

The "GetSomeHandler" method is really where the magic happens: “ GetSomeHandler”方法确实是神奇的地方:

1.At the beginning of method, an instance of the "SomeClosure" class is created. 1.在方法开始时,将创建“ SomeClosure”类的实例。 (Note that I chose to use the names "SomeHandlerClosure" and "CompilerNamedMethod" for clarity. In reality, the compiler generates names to prevent name collision.) (请注意,为清楚起见,我选择使用名称“ SomeHandlerClosure”和“ CompilerNamedMethod”。实际上,编译器会生成名称以防止名称冲突。)

2.All references to the local variable "x" in the "GetSomeHandler" method have been replaced with references to the "x" field on the "SomeHandlerClosure" instance. 2.“ GetSomeHandler”方法中对局部变量“ x”的所有引用已替换为对“ SomeHandlerClosure”实例上的“ x”字段的引用。

3.The delegate "a" is now assigned to a new delegate instance for "CompilerNamedMethod" on the "SomeHandlerClosure" instance. 3.现在,将“ SomeHandlerClosure”实例上的“ CompilerNamedMethod”分配给新的委托实例的委托“ a”。

Clear as mud?? 像泥一样清澈?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 日期时间是否在 C# 中通过引用传递? 如果不是,为什么我的 object 在我更改变量时会更新? - Are DateTimes passed by reference in C#? If not, why is my object updating as I change a variable? 为什么我的DropdownList值没有从我的后台代码传递给ASP中的C#类? - Why is my DropdownList value not being passed from my code-behind to my C# class in asp? 为什么我的变量值是Visual C#的两倍 - Why is my Variable Value Being Doubled Visual C# 当我不告诉我要通过引用传递列表时,为什么我的列表像引用一样传递? - Why is my list being passed like a reference when I did not tell it to be passed by reference? 在其他函数C#中使用传递给构造函数的引用变量 - Using reference variable passed to the constructor in other functions c# C#:传递变量时使用变量的字符串名称 - C# : using a variable when being passed it's string name C#中的属性是通过引用传递的吗? - Are properties passed by reference in C#? 为什么在 c# 中没有检测到我的 GetKeyUp? - Why is my GetKeyUp not being detected in c#? C# 如果数组是通过引用传递的,为什么必须使用修饰符 ref 传递参数数组? - C# Why does the argument array has to be passed with the modifier ref if arrays are passed by reference? 为什么c#对象的行为一次类似于按值传递,而一次按引用传递? - Why do c# objects once behave like passed by value and once as passed by reference?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM