views:

186

answers:

2

I have this method (simplified):

void DoSomething(IEnumerable<int> numbers);

And I invoke it like this:

DoSomething(condition==true?results:new List<int>());

The variable results is formed with a LINQ select condition (IEnumerable).

I was wondering is this List<int>() the best way (the fastest?) to pass an empty collection, or is new int[0] better? Or, something else would be faster, a Collection, etc.? In my example null wouldn't be ok.

+13  A: 

I'd use Enumerable.Empty<int>()

DoSometing(condition ? results : Enumerable.Empty<int>());
Lee
Nice. I've learned something today!
spender
+1. Was unaware of Enumerable.Empty
Yogendra
That's exactly what I was looking for!
avance70
From a performance perspective, `Enumerable.Empty` will be (slightly) faster than creating a new array, because the calling the `GetEnumerator()` on the `EmptyEnumerable` will return itself, while calling `GetEnumerator()` on array, will create a new object. Of course this would be a micro optimization. `Enumerable.Empty` is just more readable :-)
Steven
This is probably a question for an other thread, but what's the best way to create an IEnumerable with just 1 integer value?
avance70
@avance70: Do you care if the resulting sequence is mutable? The problem with a single-element array is that someone can then *change* the contents of it.
Eric Lippert
+1  A: 

@avance70. Not really an answer to original question, but a response to avance70's question about an IEnumerable with just 1 integer value. Would have added it as a comment, but I don't have enough rep to add a comment. If you are interested in a strictly immutable sequence, you have a couple of options:

Generic extension method:

public static IEnumerable<T> ToEnumerable<T>(this T item)
{
  yield return item;
}

Use like this:

foreach (int i in 10.ToEnumerable())
{
  Debug.WriteLine(i); //Will print "10" to output window
}

or this:

int x = 10;
foreach (int i in x.ToEnumerable())
{
  Debug.WriteLine(i); //Will print value of i to output window
}

or this:

int start = 0;
int end = 100;
IEnumerable<int> seq = GetRandomNumbersBetweenOneAndNinetyNineInclusive();

foreach (int i in start.ToEnumerable().Concat(seq).Concat(end.ToEnumerable()))
{
  //Do something with the random numbers, bookended by 0 and 100
}

I recently had a case like the start/end example above where I had to "extract" consecutive values from a sequence (using Skip and Take) and then prepend and append start and end values. The start and end values were interpolated between the last not-extracted value and the first extracted value (for start) and between the last extracted value and the first non-extracted value (for end). The resulting sequence was then operated on again, possibly reversing.

So, if original sequence looked like:

1 2 3 4 5

I might have to extract 3 and 4 and add interpolated values between 2 and 3 and 4 and 5:

2.5 3 4 4.5

Enumerable.Repeat. Use like this:

foreach (int i in Enumerable.Repeat(10,1)) //Repeat "10" 1 time.
{
  DoSomethingWithIt(i);
}

Of course, since these are IEnumerables, they can also be used in conjunction with other IEnumerable operations. Not sure if these are really "good" ideas or not, but they should get the job done.

wageoghe