c# - foreach循环,在循环语句外导出迭代集合是不是更快?

标签 c# foreach iteration enumerable

哪种方法更快,或者两者都编译为相同的 IL?

        var myCollection = new Dictionary<string, string>(){{"a", "aa"}, {"b", "bb"}, {"c", "bb"}};
        foreach (var uniqueItem in myCollection.Values.Distinct())
        {
            //do something
        }

        var myCollection = new Dictionary<string, string>() { { "a", "aa" }, { "b", "bb" }, { "c", "bb" } };
        var uniqueItems = myCollection.Values.Distinct();
        foreach (var uniqueItem in uniqueItems)
        {
            //do something
        }

最佳答案

Release模式下,两者产生相同的IL并且性能将相同(假设稍后不使用uniqueItems变量)。

在调试中,您将在启动foreach之前看到另一个分配。

编辑 - 生成 IL

private static void V1(Dictionary<string, string> myCollection)
{
    foreach (var uniqueItem in myCollection.Values.Distinct())
    {
    }
}

将编译成:

.method private hidebysig static void V1(class [mscorlib]System.Collections.Generic.Dictionary`2<string, string> myCollection) cil managed
{
    .maxstack 2
    .locals init (
        [0] string uniqueItem,
        [1] class [mscorlib]System.Collections.Generic.IEnumerator`1<string> CS$5$0000,
        [2] bool CS$4$0001)
    L_0000: nop 
    L_0001: nop 
    L_0002: ldarg.0 
    L_0003: callvirt instance class [mscorlib]System.Collections.Generic.Dictionary`2/ValueCollection<!0, !1> [mscorlib]System.Collections.Generic.Dictionary`2<string, string>::get_Values()
    L_0008: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Distinct<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
    L_000d: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> [mscorlib]System.Collections.Generic.IEnumerable`1<string>::GetEnumerator()
    L_0012: stloc.1 
    L_0013: br.s L_001e
    L_0015: ldloc.1 
    L_0016: callvirt instance !0 [mscorlib]System.Collections.Generic.IEnumerator`1<string>::get_Current()
    L_001b: stloc.0 
    L_001c: nop 
    L_001d: nop 
    L_001e: ldloc.1 
    L_001f: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
    L_0024: stloc.2 
    L_0025: ldloc.2 
    L_0026: brtrue.s L_0015
    L_0028: leave.s L_003a
    L_002a: ldloc.1 
    L_002b: ldnull 
    L_002c: ceq 
    L_002e: stloc.2 
    L_002f: ldloc.2 
    L_0030: brtrue.s L_0039
    L_0032: ldloc.1 
    L_0033: callvirt instance void [mscorlib]System.IDisposable::Dispose()
    L_0038: nop 
    L_0039: endfinally 
    L_003a: nop 
    L_003b: ret 
    .try L_0013 to L_002a finally handler L_002a to L_003a
}

可以看出,对 distinct 的调用位于 *L_0008* 中,并且没有代码跳转到此处或上方,这意味着它仅被调用一次。

关于c# - foreach循环,在循环语句外导出迭代集合是不是更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19272057/

相关文章:

C# - 按列拆分 CSV 文件

dynamic - C# 4.0 'dynamic' 和 foreach 语句

php - 如何将foreach中的字符串组合成单个字符串PHP

c# - c#/.net x.x 是否有双向链表的实现(可以向后迭代)?

C++迭代扩展容器

c++ - 在基于 C++ 范围的 for 循环中获取当前元素的索引

c# - 复杂对象/嵌套映射中的自动映射器和映射列表

c# - 如何在 Windows Server 上的 ASP.NET Core 7 中将照片转换为 webp 格式?

c# - 如何允许在 MessageBox 上复制消息

c#-4.0 - 在 foreach 循环中使用标签控件在单个标签中显示多个值