将 IEnumerable 与一项一起使用时,哪个更好:yield return 或 return []?

发布于 2024-12-17 08:02:56 字数 708 浏览 3 评论 0原文

这是“你可以通过多种方式做到这一点”问题之一。考虑以下代码:

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;
}

我只需要返回一个项目。第一段代码返回一个包含单个项目的数组,第二段代码生成该项目。 什么更好,为什么?

This is one of those "you can do it many ways" questions. Consider the following code:

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;
}

I only need to return one item. The first piece of codes returns an array with a single item and the second one yields the item. What is better and why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

为你拒绝所有暧昧 2024-12-24 08:02:56

yield 是一个非常昂贵的关键字。你告诉编译器要做很多事情。如果性能不是问题,请使用更优雅的代码。但如果性能是一个问题,请坚持使用阵列。

根据过去的经验,我可以说,摆脱这种类型的 yield 使用方式给我带来了一些显着的性能提升。但一如既往,分析并找到真正的瓶颈。

yield is a pretty expensive keyword. You are telling the compiler to do a lot. If performance isn't an issue, go with the more elegant code. But if performance is an issue, stick with the array.

I can say from past experience that getting rid of this type of yield usage has netted me some serious performance gains. But as always, profile and find the real bottlenecks.

难忘№最初的完美 2024-12-24 08:02:56

简介简介简介。这是使用 mono 的 AB 比较:(

public static IEnumerable<int> UsingYield()
{
    yield return 42;
}
public static IEnumerable<int> ReturningArray()
{
    return new []{ 42 };
}

启用 -optimize+ 编译)

yield 版本实例化一个实现 IEnumerable 的类和整个 shebang:

注意
我省略了实现枚举器块“匿名”类型 Program/'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!

Profile profile profile. Here is a A-B comparison using mono:

public static IEnumerable<int> UsingYield()
{
    yield return 42;
}
public static IEnumerable<int> ReturningArray()
{
    return new []{ 42 };
}

(Compiled with -optimize+ enabled)

The yield version instantiates a class that implements IEnumerable and the whole shebang:

Note
I left out the 163 lines of CIL code implementing the enumerator block 'anonymous' type Program/'<UsingYield>c__Iterator0'
. See it all here: 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

The array version seems much simpler:

.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

On the actual runtime performance, PROFILE PROFILE PROFILE!

悲歌长辞 2024-12-24 08:02:56

当您使用创建的数组调用它时,第一个会直接返回。

第二个,由于您使用的是yield,因此它甚至不会执行,直到您开始获取元素(在您的情况下是一个元素)。

所以这实际上取决于你想做什么,但要注意不同的行为。

The first one returns directly when you call it with the array you created it.

The second one, since you are using yield, it wont even execute until you start fetching the elements (well in your case one element).

So it really depends what you want to do, but just be aware different behavior.

信仰 2024-12-24 08:02:56

使用 Benchmark.NET 进行分析后,很明显,使用数组作为单个值比使用数组更快收益回报

使用 .NET Core 3.1.2 x64 Windows 进行测试

After profiling with Benchmark.NET , it is clear that using array for single value is faster than using yield return.

Tested using .NET Core 3.1.2 x64 Windows

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文