IEnumable 没有 Count 方法

我有以下方法:

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


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

为什么当我做 .Count()以上它是红色下划线?

我得到了以下错误:

错误1’系统. 集合. Generic.IEnumable’ 不包含 ‘ Count’和没有扩展方法 “ Count”接受第一个参数为 类型 ‘ System. Collections. Generic.IEnumable’ 可以找到(你是否遗失了一个 使用指令或程序集 参考?) c: 用户可视化文档 工作室 2010项目 Nerd逗趣晚餐 Nerd逗趣晚餐模特晚餐1547 Nerd逗趣晚餐

61549 次浏览

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(); }
}

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.

How about:

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

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.

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!