这是“你可以做很多方式”问题之一。请考虑以下代码:
protected virtual IEnumerable<ScriptReference> GetScriptReferences()
{
ScriptReference referece = new ScriptReference();
referece.Assembly = "FeyenoordEnabled";
referece.Name = "FeyenoordEnabled.PassTextBox.js";
return new ScriptReference[] { referece };
}
protected virtual IEnumerable<ScriptReference> GetScriptReferences()
{
ScriptReference referece = new ScriptReference();
referece.Assembly = "FeyenoordEnabled";
referece.Name = "FeyenoordEnabled.PassTextBox.js";
yield return referece;
}
我只需要返回一个项。第一段代码返回一个包含单个项目的数组,第二段代码生成该项目。 什么更好,为什么?
答案 0 :(得分:8)
yield
是一个非常昂贵的关键字。你告诉编译器要做很多事情。如果性能不是问题,请使用更优雅的代码。但如果性能是一个问题,坚持使用阵列。
我可以从过去的经验中说,摆脱这种yield
的使用已经让我获得了一些严重的性能提升。但与往常一样,剖析并找到真正的瓶颈。
答案 1 :(得分:5)
个人资料个人资料。这是使用mono的A-B比较:
public static IEnumerable<int> UsingYield()
{
yield return 42;
}
public static IEnumerable<int> ReturningArray()
{
return new []{ 42 };
}
(已启用-optimize+
编译)
yield版本实例化一个实现IEnumerable
的类和整个shebang:
<强> 注意 强>
我遗漏了实现枚举器块'anonymous'类型Program/'<UsingYield>c__Iterator0'
的163行CIL代码。请在此处查看:https://gist.github.com/1384014
.method public static hidebysig
default class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> UsingYield () cil managed
{
.custom instance void class [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::'.ctor'() = (01 00 00 00 ) // ....
// Method begins at RVA 0x20f4
// Code size 16 (0x10)
.maxstack 3
.locals init (
class Program/'<UsingYield>c__Iterator0' V_0)
IL_0000: newobj instance void class Program/'<UsingYield>c__Iterator0'::'.ctor'()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: dup
IL_0008: ldc.i4.s 0xfffffffe
IL_000a: stfld int32 Program/'<UsingYield>c__Iterator0'::$PC
IL_000f: ret
} // end of method Program::UsingYield
数组版本似乎更简单:
.method public static hidebysig
default class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> ReturningArray () cil managed
{
// Method begins at RVA 0x2110
// Code size 12 (0xc)
.maxstack 8
IL_0000: ldc.i4.1
IL_0001: newarr [mscorlib]System.Int32
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.i4.s 0x2a
IL_000a: stelem.i4
IL_000b: ret
} // end of method Program::ReturningArray
在实际运行时性能上,PROFILE PROFILE PROFILE!
答案 2 :(得分:4)
当您使用创建它的数组调用它时,第一个直接返回。
第二个,因为你使用yield,它甚至不会执行,直到你开始获取元素(在你的情况下一个元素)。
所以这真的取决于你想做什么,但要注意不同的行为。
答案 3 :(得分:0)
使用Benchmark.NET进行概要分析后,很明显,将数组用于单个值比使用yield return
更快。
在.NET Core 3.1.2 x64 Windows上进行了测试