-2

I have a method where I am returning IEnumerable<Data> and I wanted to check whether IEnumerable is null/empty or not. I did some research and it looks like we can use Any method of it but in my code I don't see any Any method in it so that means I am running older version of .Net?

Now I am using above method as below -

private bool Process()
{
    IEnumerable<Data> dataValue = GetData();
    // check if dataValue is null or empty
    if(dataValue != null) {
        // process entry
    }
}

What can I do to check if IEnumerable is null or empty in my case?

Update

private bool Process()
{
    IEnumerable<Data> dataValue = GetData();
    if(dataValue = null || !dataValue.Any()) {
        return false;
    }
    foreach (var x in dataValue)
    {
        // iterating over dataValue here and extracting each field of Data class
    }
}
dragons
  • 549
  • 1
  • 8
  • 24
  • 5
    Add `using System.Linq;` to the top of your `.cs` file. – Dai Jul 22 '20 at 00:45
  • 2
    `null` is not the same thing as being-empty, and `.Any()` will throw an `ArgumentNullException` if the `IEnumerable` is `null`: https://stackoverflow.com/questions/11538243/why-doesnt-any-work-on-a-c-sharp-null-object - you will need to use the **Elvis Operator**, like so: `Boolean hasAny = enumerable?.Any() ?? false;`. – Dai Jul 22 '20 at 00:45
  • Or create your own Extension `IsNullOrEmpty`. – Legacy Code Jul 22 '20 at 00:48

4 Answers4

4

There is no need for an explicit Any check or null check.

foreach (var x in (dataValue ?? Enumerable.Empty<Data>()))

is what I would suggest, since it avoids the double enumeration problem of using Any (and it treats null as equivalent to empty). So this might look like:

private bool Process()
{
    bool returnValue = false;
    IEnumerable<Data> dataValue = GetData();
    foreach (var x in (dataValue ?? Enumerable.Empty<Data>()))
    {
        returnValue = true;
        // iterating over dataValue here and extracting each field of Data class
    }

    return returnValue;
}
mjwills
  • 23,389
  • 6
  • 40
  • 63
  • Any() is an O(1) operation. And if you look at the source it enumerates to the first item then returns true if it found one. – JoshBerke Jul 24 '20 at 23:20
  • @JoshBerke If the underlying enumerable was `IQueryable` (e.g. getting from a database) then `Any` will cause an extra DB query (similar issues can occur if it is a `yield return` solution etc). And there is no guarantee that the data used in `Any` will be the same data used in the `foreach` (for example). You may wish to read https://www.jetbrains.com/help/resharper/PossibleMultipleEnumeration.html, https://stackoverflow.com/questions/48932548/multiple-enumeration-and-use-of-any and https://stackoverflow.com/questions/8240844/handling-warning-for-possible-multiple-enumeration-of-ienumerable . – mjwills Jul 25 '20 at 07:08
  • Ok, I don't deal with any IQueryable implementations that hit the DB (At least not a normal basis). And glad I don't, seems like a nasty side effect that is counter intuitive. – JoshBerke Jul 29 '20 at 13:53
  • @JoshBerke It is by design and well documented. – mjwills Jul 29 '20 at 22:19
  • just because its intentional and well documented doesn't mean its a good implementation. It's a side effect that as your writing the code you might be unaware. If I was to write a library that consumed an IEnumerable, and I had to do multiple enumerations on it for some reason, and developer comes along and sends an IQueryable.... – JoshBerke Jul 31 '20 at 18:47
  • @JoshBerke The issue isn't _just_ with `IQueryable`. It is a risk with many enumerables (example - https://dotnetfiddle.net/Xsvtdu - note that `Any` "lost" the second 1). The point is `Any` does not guarantee it is `O(1)`, despite your assertion, and it doesn't guarantee it doesn't enumerate (which when you think about it is intuitive - it _has_ to enumerate in some cases to work out if there is an entry or not). Explaining the finer details to you is hard in a comment-based context. If you write up a new question I can add an answer for you there, or point you to some good resources. – mjwills Aug 01 '20 at 00:36
  • No need, your fiddle was a great example. – JoshBerke Aug 04 '20 at 17:35
0

Usually

dataValue != null && dataValue.Any()

You may have to add using System.Linq;

Luke Storry
  • 6,032
  • 1
  • 9
  • 22
0

You can also use

if (dataValue?.Any()==true)
{}

I wish you could just say

if(dataValue?.Any())

but that won't compile:-)

JoshBerke
  • 66,142
  • 25
  • 126
  • 164
0

We use a following method that is similar to LINQ's Single() extension, provided enumeration should not be empty:

  public static IEnumerable<T> Required<T>(this IEnumerable<T>? source)
  {
    var empty = true;

    if (source != null)
    {
      using var enumerator = source.GetEnumerator();

      while(enumerator.MoveNext())
      {
        yield return enumerator.Current;

        empty = false;
      }
    }

    if (empty)
    {
      throw new InvalidOperationException("Source should be non empty.");
    }
  }

It's virtue in that it passes enumeration once.