Dou*_*ell 3 c# value-type reference-type
我浏览了一些 C# 示例并发现了以下内容:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
delegate void Printer();
static void Main()
{
List<Printer> printers = new List<Printer>();
for (int i = 0; i < 10; i++)
{
printers.Add(delegate { var d = i; Console.WriteLine(d); });
}
foreach (var printer in printers)
{
printer();
}
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我期望它0通过输出9,因为 anint是一种值类型,d应该设置为i当时的任何值。
然而,这输出了10十倍。
为什么是这样?int 不是一个引用而是在委托内部吗?
注意:我并不是想在这里解决问题,只是以可重复应用的方式了解它是如何工作的。
编辑:我的困惑的例子
int i = 9;
int d = 8;
d = i;
i++;
Console.WriteLine(d);
Run Code Online (Sandbox Code Playgroud)
这表明它i是作为值传递的,而不是引用。我预计封口内也会有同样的情况,但感到惊讶。
感谢您的评论,我现在了解更多了,委托中的代码直到之后才执行,并且它使用i编译器生成的泛型类中存在的代码?
在 javascript 中,同样类型的代码输出 1-9,这正是我在 C# 中所期望的。https://jsfiddle.net/L21xLaq0/2/。
您可能有兴趣了解编译器实际上如何重写这段代码,因为它有助于理解发生了什么。如果您编译然后在禁用“花式视图”的某些反编译器(如 dotPeek)中查看 dll,您将看到以下内容(某些名称已更改,因为它们不可读):
class Program {
delegate void Printer();
private static void Main() {
List<Program.Printer> printerList = new List<Program.Printer>();
// closure object which holds captured variables
Program.DisplayClass10 cDisplayClass10 = new Program.DisplayClass10();
int i;
// loop assigns field of closure object
for (cDisplayClass10.i = 0; cDisplayClass10.i < 10; cDisplayClass10.i = i + 1) {
// your delegate is method of closure object
printerList.Add(new Program.Printer(cDisplayClass10.CrypticFunctionName));
i = cDisplayClass10.i;
}
// here, cDisplayClass10.i is 10
foreach (Program.Printer printer in printerList)
printer();
Console.ReadLine();
}
// class for closure object
[CompilerGenerated]
private sealed class DisplayClass10 {
public int i;
internal void CrypticFunctionName() {
Console.WriteLine(this.i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2415 次 |
| 最近记录: |