What is better when using an IEnumerable with one item: yield return or return []?

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.


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!


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.