C# 将IEnumerable与一个项目一起使用时,有什么更好的方法:收益回报或回报[]?
这是一个“你可以用很多方法”的问题。考虑下面的代码:C# 将IEnumerable与一个项目一起使用时,有什么更好的方法:收益回报或回报[]?,c#,.net,ienumerable,yield,C#,.net,Ienumerable,Yield,这是一个“你可以用很多方法”的问题。考虑下面的代码: protected virtual IEnumerable<ScriptReference> GetScriptReferences() { ScriptReference referece = new ScriptReference(); referece.Assembly = "FeyenoordEnabled"; referece.Name = "FeyenoordEnabled.PassTextBo
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;
}
受保护的虚拟IEnumerable GetScriptReferences()
{
ScriptReference referece=新ScriptReference();
referece.Assembly=“FeyenoordEnabled”;
referece.Name=“FeyenoordEnabled.PassTextBox.js”;
返回新的ScriptReference[]{referece};
}
受保护的虚拟IEnumerable GetScriptReferences()
{
ScriptReference referece=新ScriptReference();
referece.Assembly=“FeyenoordEnabled”;
referece.Name=“FeyenoordEnabled.PassTextBox.js”;
收益率参考;
}
我只需要返回一项。第一段代码返回一个包含单个项的数组,第二段代码生成该项什么更好?为什么?
收益率是一个非常昂贵的关键词。你告诉编译器要做很多事情。如果性能不是问题,请使用更优雅的代码。但是,如果性能有问题,请使用阵列
根据过去的经验,我可以说,摆脱这种类型的yield
使用,我获得了一些显著的性能提升。但与往常一样,请分析并找到真正的瓶颈。当您使用创建的数组调用它时,第一个瓶颈会直接返回
第二个,因为您使用的是yield,所以在开始获取元素之前,它甚至不会执行(在您的示例中是一个元素)
所以这实际上取决于你想做什么,但要注意不同的行为。Profile。以下是使用mono进行的a-B比较:
public static IEnumerable<int> UsingYield()
{
yield return 42;
}
public static IEnumerable<int> ReturningArray()
{
return new []{ 42 };
}
阵列版本似乎简单得多:
.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
.method公共静态隐藏
默认类[mscorlib]System.Collections.Generic.IEnumerable`1 ReturningArray()cil托管
{
//方法从RVA 0x2110开始
//代码大小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
}//方法结束程序::ReturningArray
在实际运行时性能上,配置文件 使用分析后,很明显,对单个值使用数组比使用产生返回要快
使用.NET Core 3.1.2 x64 Windows进行测试肯定不可能比第一个返回
更有效吗?您也可以返回可枚举的。重复(参考文献1)代码>虽然这归结为封面下的收益回报
,但我要指出收益
还有一个用途:创建一个生成的、无休止的IEnumerable(例如,一个Fibonnaci序列生成器)。如果要这样做,就必须小心不要试图循环遍历整个IEnumerable。但是,有趣的是,我可以告诉您,出于性能原因,只要明智的话,我都会避免收益率回报。似乎其他人正在确认这一做法。如果收益率
如此昂贵,什么时候使用so“正确”呢?Linq基于收益率关键字的使用。yield使函数变得懒惰,如果不获取元素,则什么也不会发生。您发布的案例,直接返回是有意义的,不需要使用收益率。如果收益率
如此昂贵,那么什么时候使用so才是“正确的”?@KeesC.Bakker:就生成的代码而言,它是复杂的。您使用它的原因在别处提到过:(a)延迟执行(b)抽象(您以程序员看不到的复杂性为代价获得状态机功能)。而且,没有人说JIT引擎不会内联相关的方法并获得接近相同的结果。简介,简介,简介!好的,先知先生……”从今天起,我要出去走走!”对于那些不想分析的人来说,C#7/.NET4.7在产生回报方面有轻微的速度优势。
.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