11
public class Stuff
{
  public int x;
  // ... other stuff
}

I have a IEnumerable<Stuff> and I want to build a int[] of all of the x properties of all the Stuff objects in the collection.

I do:

IEnumerable<Stuff> coll;
// ...
var data = coll.Select(s => s.x).ToArray();

What I want is a null array rather than a int[0] if the collection is empty. In other words, if !coll.Any(), then I want data = null. (My actual need is that coll is an intermediate result of a complex LINQ expression, and I would like to do this with a LINQ operation on the expression chain, rather than saving the intermediate result)

I know that int[0] is more desirable than null in many contexts, but I am storing many of these results and would prefer to pass around nulls than empty arrays.

So my current solution is something like:

var tmp = coll.Select(s => s.x).ToArray();
int[] data = tmp.Any() ? tmp : null;

Any way to do this without storing tmp?

EDIT: The main question is how to do this without storing intermediate results. Something like NULLIF() from T-SQL where you get back what you passed in if the condition is false, and NULL if the condition is true.

3 Answers 3

15

If you're doing this a lot, you could write an extension method:

public static class IEnumerableExt
{
    public static T[] ToArrayOrNull<T>(this IEnumerable<T> seq)
    {
        var result = seq.ToArray();

        if (result.Length == 0)
            return null;

        return result;
    }
}

Then your calling code would be:

var data = coll.Select(s => s.x).ToArrayOrNull();
Sign up to request clarification or add additional context in comments.

1 Comment

I like this approach very much. You could also add a check for seq == null if you wanted null safety, unlike my previous solution.
3

Create the array only if coll is not empty, so the other way round:

int[] data = null;
if(coll.Any()) data = coll.Select(s => s.x).ToArray();

Comments

1

There's not a way to get Select to return null, but if you don't want to create an additional array you could do:

var tmp = coll.Select(s => s.x);
int[] data = tmp.Any() ? tmp.ToArray() : null;

3 Comments

Why iterate the results twice, instead of what OP currently has ?
Any() will return immediately either because the projection is empty or has at least one element, so it's not enumerating the entire collection twice.
But if coll is a "LINQ to SQL" or other heavy-lifting expression, it will do the work twice, and may potentially even be inconsistent between executions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.