locked
No .Count on IEnumerable? RRS feed

  • Question

  • I'm wondering why there is no .Count on the following IEnumerable below.  I need to check to see if the incoming list has any data

    private static void RenderProducts(TextWriter writer, IEnumerable<Product> products)

    {

        //...code

    }

     

    In other words I cannot do if(products.Count == 0) or (products.Count < 1) which is the same thing on the list for some reason


    C# Web Developer
    Thursday, July 1, 2010 3:03 PM

Answers

  • Here's the example (note the use of ".Any()" as suggested by Deborah):

    using System;
    using System.Linq;
    using System.Collections.Generic;
    
    namespace Demo
    {
      class Program
      {
        static void Main(string[] args)
        {
          var sequences = new DemoSequences();
    
          PrintSequence("Empty sequence:",  sequences.EmptySequence);
          PrintSequence("Finite sequence:",  sequences.FiniteSequence);
          PrintSequence("Infinite sequence:", sequences.InfiniteSequence);
        }
    
        static void PrintSequence<T>(string title, IEnumerable<T> sequence)
        {
          Console.WriteLine(title);
    
          if (!sequence.Any())
          {
            Console.WriteLine("Sequence has no elements.");
          }
    
          foreach (var item in sequence)
          {
            Console.WriteLine(item);
          }
    
          Console.WriteLine();
        }
      }
    
      public class DemoSequences
      {
        public IEnumerable<int> EmptySequence
        {
          get
          {
            yield break;
          }
        }
    
        public IEnumerable<int> FiniteSequence
        {
          get
          {
            for (int i = 0; i < 10; ++i)
            {
              yield return i;
            }
          }
        }
    
        public IEnumerable<int> InfiniteSequence
        {
          get
          {
            while (true)
            {
              yield return 0;
            }
          }
        }
      }
    }
    

    Thursday, July 1, 2010 3:44 PM
  • You should be able to do products.Any(). That will return whether the enumeration has any elements.

    Hope this helps.


    www.insteptech.com ; msmvps.com/blogs/deborahk
    We are volunteers and ask only that if we are able to help you, that you mark our reply as your answer. THANKS!
    Thursday, July 1, 2010 3:44 PM
  • In .NET 2, you can enumerate it and check for members:

        bool hasElements = collection.GetEnumerator().MoveNext();

     

    That's basically the same as calling .Any() on a collection without using the LINQ extensions.  That being said, I'd always use the .NET 3.5+ versions when you're working on new development.


    Reed Copsey, Jr. - http://reedcopsey.com
    Thursday, July 1, 2010 7:04 PM

All replies

  • An IEnumerable doesn't have to know the size of its collection until you enumerate it, so it cannot have a count. You could, for example, have an IEnumerable that returned prime numbers that never ended.

    If an IEnumerable had to have a count, that would basically make it an ICollection instead.

    Thursday, July 1, 2010 3:11 PM
  • Thanks, did not know all that.  I'll jot that down for the future.  I haven't dealt with much IEnumerable to know this.

     

    So then I should always be checking for null in this case then if I want to be sure the collection incoming is valid?


    C# Web Developer
    Thursday, July 1, 2010 3:22 PM
  • Well you don't normally represent an empty collection with a null enumerator. In our code, we throw an ArgumentNullException if someone passes in a null enumerator (or a null collection).

    If you need to know in advance how many items are in it, you really should be using an ICollection<> or an IList<>.

    If you only need to know if the sequence is not empty, use " if (sequence.Any())"

    Hang on a sec and I'll post an example showing enumerators that represent empty, finite and infinite sequences.

    [EDIT] Updated information with Deborah's contribution.

    Thursday, July 1, 2010 3:28 PM
  • Here's the example (note the use of ".Any()" as suggested by Deborah):

    using System;
    using System.Linq;
    using System.Collections.Generic;
    
    namespace Demo
    {
      class Program
      {
        static void Main(string[] args)
        {
          var sequences = new DemoSequences();
    
          PrintSequence("Empty sequence:",  sequences.EmptySequence);
          PrintSequence("Finite sequence:",  sequences.FiniteSequence);
          PrintSequence("Infinite sequence:", sequences.InfiniteSequence);
        }
    
        static void PrintSequence<T>(string title, IEnumerable<T> sequence)
        {
          Console.WriteLine(title);
    
          if (!sequence.Any())
          {
            Console.WriteLine("Sequence has no elements.");
          }
    
          foreach (var item in sequence)
          {
            Console.WriteLine(item);
          }
    
          Console.WriteLine();
        }
      }
    
      public class DemoSequences
      {
        public IEnumerable<int> EmptySequence
        {
          get
          {
            yield break;
          }
        }
    
        public IEnumerable<int> FiniteSequence
        {
          get
          {
            for (int i = 0; i < 10; ++i)
            {
              yield return i;
            }
          }
        }
    
        public IEnumerable<int> InfiniteSequence
        {
          get
          {
            while (true)
            {
              yield return 0;
            }
          }
        }
      }
    }
    

    Thursday, July 1, 2010 3:44 PM
  • You should be able to do products.Any(). That will return whether the enumeration has any elements.

    Hope this helps.


    www.insteptech.com ; msmvps.com/blogs/deborahk
    We are volunteers and ask only that if we are able to help you, that you mark our reply as your answer. THANKS!
    Thursday, July 1, 2010 3:44 PM
  • Just to be explicit, doing:

    if (sequence.Any()) ...

    is the same as doing:

    if (sequence.GetEnumerator().MoveNext()) ...

    So be aware that if GetEnumerator() is doing lots of work for that sequence, there will be some overhead.

    Thursday, July 1, 2010 3:50 PM
  • I'm wondering why there is no .Count on the following IEnumerable below.  I need to check to see if the incoming list has any data

    private static void RenderProducts(TextWriter writer, IEnumerable<Product> products)

    {

        //...code

    }

     

    In other words I cannot do if(products.Count == 0) or (products.Count < 1) which is the same thing on the list for some reason


    C# Web Developer

    If you're using .NET 3.5, you can use the .Count() extension method.  

     

    That being said, I agree with the other posters - .Any() is a better option for testing to see if "any" elements exist.  Count() is not as good as Any(), because Count() will force the enumerable to enumerate through every element in order to get a full count - Any() will just check to see if a single element exists, and stop enumerating.

     


    Reed Copsey, Jr. - http://reedcopsey.com
    Thursday, July 1, 2010 4:01 PM
  • Reed thanks for the performance tip.

    In our case we DON'T want to throw an exception because we do not want to halt our method which resides in a web service.  If we throw an exception, then the methods in this case that sets up the response data will never complete and the response never sent back to the client.  So if you don't normally check for null (and yes now I debugged and see that a list normally at least has a length of 0 if nothing is in it) then I need some way to check to see if the list has any values.

    So the .Any() is perfect..thanks.  But what if I did not have LINQ?  What if this were a .NET 2.0 or 1.1 app?  I like to figure things out not just based on 3.5 just because I cannot be absolutely sure that wherever I work it will always be 100% .NET 3.5 or 4.0

    C# Web Developer
    Thursday, July 1, 2010 6:34 PM
  • In .NET 2, you can enumerate it and check for members:

        bool hasElements = collection.GetEnumerator().MoveNext();

     

    That's basically the same as calling .Any() on a collection without using the LINQ extensions.  That being said, I'd always use the .NET 3.5+ versions when you're working on new development.


    Reed Copsey, Jr. - http://reedcopsey.com
    Thursday, July 1, 2010 7:04 PM
  • Reed thanks for the performance tip.

    In our case we DON'T want to throw an exception because we do not want to halt our method which resides in a web service.  If we throw an exception, then the methods in this case that sets up the response data will never complete and the response never sent back to the client.  So if you don't normally check for null (and yes now I debugged and see that a list normally at least has a length of 0 if nothing is in it) then I need some way to check to see if the list has any values.

    So the .Any() is perfect..thanks.  But what if I did not have LINQ?  What if this were a .NET 2.0 or 1.1 app?  I like to figure things out not just based on 3.5 just because I cannot be absolutely sure that wherever I work it will always be 100% .NET 3.5 or 4.0

    C# Web Developer
    See my previous post where I showed the .Net 3.5 equivalent, or Reed's answer below. :)
    Thursday, July 1, 2010 9:28 PM
  • Hi NoEgo,

     

    I am writing to check the status of the issue on your side.  Would you mind letting us know the result of the suggestions? 

     

    If you need further assistance, please feel free to let me know.   I will be more than happy to be of assistance.

     

    Have a nice day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Tuesday, July 6, 2010 1:16 AM
  • Hi NoEgo,

     

    I am writing to check the status of the issue on your side.  Would you mind letting us know the result of the suggestions? 

     

    If you need further assistance, please feel free to let me know.   I will be more than happy to be of assistance.

     

    Have a nice day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Monday, July 12, 2010 8:05 AM