Is there any way to optionally return a null with a \"return yield\" driven iterator?
I would like to return a null in some cases and I don\'t think this is particul
This just isn't encouraged. When you're talking about a sequence, "null" should generally have the same semantics as "empty list."
Also, it's impossible to design the language to work in the way you'd like it to work here without extra syntax, since what if you were to hit a "yield return [whatever]
" and then a "return null
?"
There is nothing that prevents you from doing a yield return null;
, if it is appropriate (of course, the enumerated type must be nullable).
While yield break
is propably the best answer and it really does not matter since you always can do Items.Count()
to check if greater zero or even do for each on your empty result
there could be situations where it does matter if your result is an empty list or nothing at all and you still want to utilize the power of yield.
In that case this will help.
private IEnumerable<T> YieldItems<T>(IEnumerable<T> items, Action empty = null)
{
if (items == null)
{
if (empty != null) empty();
yield break;
}
foreach (var item in items)
{
yield return item;
}
}
Usage
foreach (var item in YieldItems<string>(null, () =>
{
Console.WriteLine("Empty");
}))
{
Console.WriteLine(item);
}
You're not using an enumerable as it was intended (to iterate objects in a collection). If you want to keep your code similar to what it is now, you should do something like this:
static void Main(string[] args)
{
var Items = GetItems();
foreach (var item in Items) //this will not enter the loop because there are no items in the Items collection
{
Console.WriteLine(item);
}
//if you still need to know if there were items, check the Count() extension method
if(Items.Count() == 0)
{
Console.WriteLine("0 items returned");
}
}
static IEnumerable<string> GetItems()
{
if (false)
{
yield return "Andy";
yield return "Jennifer";
}
yield break;
}
If you need to things like that (or throw things like ArgumentException
immediately), you need to separate your iterator into two methods:
public IEnumerable<string> GetItems() {
if (something) return null;
return GetItemsInternal();
}
private IEnumerable<string> GetItemsInternal() {
// the actual iterator with "yield return" goes here.
}
There is no way to return a null IEnumerable<T>
from within an iterator method. You can return null values in the iterator but not a null IEnumerable<T>
What you could do though is have a wrapper method which either returns null or calls to the real iterator
static IEnumerable<string> GetItems() {
if (false) {
return GetItemsCore();
}
return null;
}
static IEnumerable<string> GetItemsCore() {
yield return "Andy";
yield return "Jennifer";
}