Ami*_*tan 2 c# memory lazy-evaluation yield-return
你可以告诉我在执行以下代码时内存中发生了什么:
情况1:
public static void Execute()
{
foreach(var text in DownloadTexts())
{
Console.WriteLine(text);
}
}
public static IEnumerable<string> DownloadTexts()
{
foreach(var url in _urls)
{
using (var webClient = new WebClient())
{
yield return webClient.DownloadText(url);
}
}
}
Run Code Online (Sandbox Code Playgroud)
让我们假设在第一次迭代后我得到html1.
什么时候从内存中清除html1?
谢谢
**编辑**
案例2:
public static void Execute()
{
var values = DownloadTexts();
foreach(var text in values)
{
Console.WriteLine(text);
}
}
public static IEnumerable<string> DownloadTexts()
{
foreach(var url in _urls)
{
using (var webClient = new WebClient())
{
yield return webClient.DownloadText(url);
}
}
}
Run Code Online (Sandbox Code Playgroud)
根据我的理解,案例1对记忆更好,然后案例2对吗?
在案例2中,仍然会保留对我们已经下载的文本的引用,而在案例1中,每个文本在未使用后都标记为垃圾回收.我对么?
_urls 将无限期地停留,因为它看起来像是在一个领域.DownloadTexts() (由它返回的迭代器)保持活动直到循环结束.WebClient和html它产生活着的一个迭代.如果您想知道它的绝对精确寿命,您需要使用Reflector并在心理上模拟参考传播的位置.你会发现IEnumerator循环中使用的引用它直到下一次迭代开始.所有不活动的对象都可以进行GC操作.只要GC认为这是一个好主意,就会发生这种情况.
关于你的编辑:案例是等价的.如果不将枚举数放入变量中,编译器将为您执行此操作.它必须保持引用直到循环结束.有多少引用并不重要.至少有一个.
实际上,循环只需要使枚举器保持活动状态.您添加的其他变量也将使可枚举值保持活动状态.另一方面,您没有使用变量,因此GC不会使其保持活动状态.
您可以轻松测试:
//allocate 1TB of memory:
var items =
Enumerable.Range(0, 1024 * 1024 * 1024)
.Select(x => new string('x', 1024));
foreach (var _ in items) { } //constant memory usage
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
251 次 |
| 最近记录: |