0

I have this code

public static class FallbackUtils<TResult, TRequest>
      where TRequest : IFallbackRequest
   {
      public static IEnumerable<TResult> GetAllValues(TRequest request,
         Func<TRequest, TResult> callback)          
      {
         yield return callback(request);

         while (request.CanFallback())
         {
            request.Fallback();
            yield return callback(request);
         }
      }  
   }

Sometimes TResult is going to be an IEnumerable. In those cases I want to be able to keep not only null but empty collections from being returned. The problem is that I don't know how to ask TResult if it's empty I know only how to ask if it's null. Something like this

public static IEnumerable<TResult> GetAllValues(TRequest request,
         Func<TRequest, TResult> callback, bool ignoreNullOrEmpty = false)          
      {
         var item = callback(request);

         if (ignoreNullOrEmpty)
         {
            if (item != null && item.Any())
               yield return item;
         }
         else
            yield return item;

         while (request.CanFallback())
         {
            request.Fallback();

            item = callback(request);
            if (ignoreNullOrEmpty)
            {
               if (item != null && item.Any())
                  yield return item;
            }
            else
               yield return item;
         }
      }

I want to do the filtering inside this method to clean up a lot of duplicate code that is doing this same thing.

Any ideas of what should I do or what I'm doing wrong? Thanks in advance.

Chorinator
  • 1,317
  • 12
  • 13

2 Answers2

3

If you need to know if your TResult is IEnumerable, then you just need try to cast to it. Afterwards you can handle the empty collection and null values as follows:

// is it an IEnumerable?
var item = callback(request);
var enumerable = item as IEnumerable;
if(enumerable != null) 
{
  var enumerator = enumerable.GetEnumerator();
  if(!enumerator.MoveNext())
  {
     // handle an empty collection here
  }
  else
  {
     do 
     {
        if(enumerator.Current == null)
          // handle the null value here
     } while(enumerator.MoveNext());
  }
}

Since you probably do not know the type of the items being inside the IEnumerable, you cannot use IEnumerable<T> and Linq extensions.

Edin
  • 1,476
  • 11
  • 21
2

Well there is no Any method on IEnumerable, you could write your own method:

public static bool Any(this IEnumerable source)
{
    var enumerator = source.GetEnumerator();

    return enumerator.MoveNext();
}

Then you can call it:

if (item != null && 
    item is IEnumerable && 
    ((IEnumerable)item).Any())
Selman Genç
  • 100,147
  • 13
  • 119
  • 184