Search code examples
c#ienumerablec#-6.0yield-returnc#-7.0

IEnumerable Expression-Bodied Member C#


I have a get-only property in C# that returns an IEnumerable. If that property will only ever yield once, then I could define my property like so:

public IEnumerable Derp {
    get { yield return new SomeObject(); }
}

But how would I do this with a C#6 expression-bodied member? The following approaches do NOT work:

// These definitions do NOT work
public IEnumerable Derp => yield return new SomeObject();
public IEnumerable Derp => yield new SomeObject();

returning compiler error CS0103: "The name 'yield' does not exist in the current context". Is a yielding expression-bodied member even possible in C#6? How about in C#7?

I'm aware that an IEnumerable member that only returns once looks smelly, but I'm mainly just curious. I came across this situation while experimenting with the NUnit TestCaseSource API, trying to provide a method that yields only one test case. I could also see this being relevant to Unity developers who want to define an expression-bodied method to be called with StartCoroutine().

Anyway, thanks in advance for your thoughts!


Solution

  • Expression-bodied functions/properties can't have statements... You can't, for example:

    static int Test(int x) => if (x > 0) x else 0;
    

    or even

    static int Test(int x) => return x;
    

    yield is a statement... You can't use it :-)

    Note that you can:

    IEnumerable<SomeObject> Derp => new[] { new SomeObject() };
    

    From the Roslyn github page, New Language Features in C# 6:

    2.1 Expression bodies on method-like members Methods as well as user-defined operators and conversions can be given an expression body by use of the “lambda arrow”:

    The effect is exactly the same as if the methods had had a block body with a single return statement.

    For void returning methods – and Task returning async methods – the arrow syntax still applies, but the expression following the arrow must be a statement expression (just as is the rule for lambdas):

    So there is an exception for void returning methods, but still it only covers calling methods (you can => Console.WriteLine("Hello"); but you can't => if ()).