86
votes

I have the following method:

public bool IsValid
{
  get { return (GetRuleViolations().Count() == 0); }
}

public IEnumerable<RuleViolation> GetRuleViolations(){
  //code here
}

Why is it that when I do .Count() above it is underlined in red?

I got the following error:

Error 1 'System.Collections.Generic.IEnumerable' does not contain a definition for 'Count' and no extension method 'Count' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found (are you missing a using directive or an assembly reference?) c:\users\a\documents\visual studio 2010\Projects\NerdDinner\NerdDinner\Models\Dinner.cs 15 47 NerdDinner

5
Had same problem. For some reason you can't right-click this and choose "Resolve ..." to fix it :( - micahhoover
Sigh! I have System.Linq included but still get this error. (Though he error message names the first arg as "System.Linq.IQueryable".) - Hot Licks
On a general note: Be way of the shortcomings of .Count() - don't use it lightheartedly! I've written about it in my comment below stackoverflow.com/a/65112753/863651 Feel free to review it - XDS

5 Answers

165
votes

You add:

using System.Linq;

at the top of your source and make sure you've got a reference to the System.Core assembly.

Count() is an extension method provided by the System.Linq.Enumerable static class for LINQ to Objects, and System.Linq.Queryable for LINQ to SQL and other out-of-process providers.

EDIT: In fact, using Count() here is relatively inefficient (at least in LINQ to Objects). All you want to know is whether there are any elements or not, right? In that case, Any() is a better fit:

public bool IsValid
{
  get { return !GetRuleViolations().Any(); }
}
10
votes

Any() or Count() methods in Linq work only for generic types.

IEnumerable<T>

If you have a simple IEnumerable without a type, try to use

IEnumerable<object> 

instead.

2
votes

IEnumeration does not have a method called Count(). It's just a kind of "sequence of elements". Use for example List if you explicitly need the number of elements. If you use Linq keep in mind, that the extension method Count() may actually re-count the number of elements each time you call it.

0
votes

A short & sweet general word of caution on the pitfalls of .Count() to help the weary traveler that stumbles upon this post in the future!

Short story:

The following works -no doubt- but there might small performance penalty if the enumerables is not backed by an underlying array or list which has the 'count' in handy/precomputed:

public bool IsValid
{
   get { return SomeMethodReturningEnumerable().Count() <= threshold; }  <--- small performance issue here
}

public IEnumerable<SomeObject> SomeMethodReturningEnumerable(){
   yield return foo;
   yield return bar; etc
}

The call to the .Count() method will probably go through each and every item in the enumerable and then compare the overall count against threshold. We being smarter can do a bit better:

    public bool IsValid
    {
       get { return !SomeMethodReturningEnumerable().HasMoreThan(threshold); }  <--- neato!
    }

    public static bool HasLessThan<T>(this IEnumerable<T> sequence, int count) => !sequence.HasMoreThan(count - 1);

    public static bool HasLessOrEqualTo<T>(this IEnumerable<T> sequence, int count) => !sequence.HasMoreThan(count);

    public static bool HasMoreOrEqualTo<T>(this IEnumerable<T> sequence, int count) => sequence.HasMoreThan(count - 1);

    public static bool HasMoreThan<T>(this IEnumerable<T> sequence, int count) => sequence.EnumerationCounterImpl(count, equals_vs_greaterThan: false);

    public static bool HasExactly<T>(this IEnumerable<T> sequence, int count) => sequence.EnumerationCounterImpl(count, equals_vs_greaterThan: true);

    public static bool EnumerationCounterImpl<T>(this IEnumerable<T> sequence, int count, bool equals_vs_greaterThan = true) //0
    {
        if (equals_vs_greaterThan && count < 0)
            throw new ArgumentException($"{nameof(count)} is less than zero!");

        if (!equals_vs_greaterThan && count < 0)
            return true;

        var staticCount = (sequence as ICollection)?.Count                              
                          ?? (sequence as ICollection<T>)?.Count
                          ?? (sequence as IReadOnlyCollection<T>)?.Count;

        if (staticCount != null)
            return staticCount > count;

        using (var enumerator = sequence.GetEnumerator()) //1 optimization
        {
            for (int i = 0; i < count + 1; i++)
            {
                if (enumerator.MoveNext())
                    continue;

                return false;
            }

            return !equals_vs_greaterThan //     ==
                   || enumerator.MoveNext(); //  >
        }

        //0 https://blog.slaks.net/2015-01-12/linq-count-considered-occasionally-harmful/
        //1 using the enumerator directly is slightly faster than using LINQ methods   it avoids allocating an extra iterator
        //  state machine compared to using skip()
    }

There! Problem solved again but this time around we are performance-conscious!

-1
votes

How about:

public bool IsValid
{
    get { return (GetRuleViolations().Cast<RuleViolation>().Count() == 0); }
}