IEnumerable не має методу Count


83

У мене є такий спосіб:

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

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

Чому коли я роблю .Count()вище, це підкреслюється червоним?

Я отримав таку помилку:

Помилка 1 'System.Collections.Generic.IEnumerable' не містить визначення для 'Count' і не може бути знайдено жодного методу розширення 'Count', що приймає перший аргумент типу 'System.Collections.Generic.IEnumerable' (вам не вистачає за допомогою директиви або посилання на збірку?) c: \ users \ a \ documents \ visual studio 2010 \ Projects \ NerdDinner \ NerdDinner \ Models \ Dinner.cs 15 47 NerdDinner


Була така сама проблема. З якоїсь причини ви не можете клацнути правою кнопкою миші та вибрати "Вирішити ...", щоб виправити це :(
micahhoover

Зітхайте! Я включив System.Linq, але все одно отримую цю помилку. (Хоча в повідомленні про помилку перший аргумент називається "System.Linq.IQueryable".)
Hot Licks

Загальна примітка: Помітьте недоліки .Count () - не використовуйте його несерйозно! Я писав про це у своєму коментарі нижче stackoverflow.com/a/65112753/863651 Не соромтеся переглядати це
XDS

Відповіді:


160

Ви додаєте:

using System.Linq;

у верхній частині джерела та переконайтеся, що у вас є посилання на збірку System.Core.

Count()- це метод розширення, наданий System.Linq.Enumerableстатичним класом для LINQ to Objects, а також System.Linq.Queryableдля LINQ to SQL та інших позапроцесорних постачальників.

EDIT: Насправді використання Count()тут є відносно неефективним (принаймні в LINQ to Objects). Все, що ви хочете знати, - це якісь елементи чи ні, правда? У такому випадку Any()краще підходить:

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

Якщо це посилання видає помилку, переконайтеся, що для Target Framework вашого проекту (у властивостях проекту, вкладка Application) встановлено .NET Framework 3.5 або 4. Методи розширення не працюватимуть у версії 2.0 або раніше.
willvv

1
Я використовував System.Linq; але це не вирішує мою проблему ... як я можу переконатися, що я отримав посилання на збірку System.Core?
aherlambang,

О, нічого, я це виправив ... чим відрізняється System.data.linq від System.Linq
aherlambang

@Alexander: Це абсолютно різні простори імен. System.Data.Linqє специфічним для LINQ to SQL.
Джон Скіт,

1
@skyfoot: Ні, насправді не буде. Це дасть вам 4. Якщо ви думаєте інакше, надішліть запитання із короткою, але повною програмою, яка демонструє проблему.
Джон Скіт,

7

Any()або Count()методи в Linq працюють лише для загальних типів.

IEnumerable<T>

Якщо у вас є простий IEnumerableбез типу, спробуйте використовувати

IEnumerable<object> 

натомість.


2

IEnumerationне має методу, який називається Count(). Це просто своєрідна «послідовність елементів». Використовуйте, наприклад, Listякщо вам явно потрібна кількість елементів. Якщо ви використовуєте Linq, майте на увазі, що метод розширення Count()може насправді перераховувати кількість елементів кожного разу, коли ви його викликаєте.


0

Коротке та солодке загальне слово застереження щодо підводних каменів .Count (), щоб допомогти втомленому мандрівнику, який натрапить на цей пост у майбутньому!

Коротка розповідь:

Наступне працює - без сумніву - але може виникнути невелика покарання за продуктивність, якщо перерахування не підтримуються базовим масивом або списком, який має підрахунок / попередньо обчислений:

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

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

Виклик методу .Count (), ймовірно, пройде кожен елемент у переліченному, а потім порівняє загальний підрахунок до порогового значення. Ми, розумніші, можемо зробити трохи краще:

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

Ось! Проблема вирішена знову, але цього разу ми усвідомлюємо продуктивність!


-1

Як щодо:

public bool IsValid
{
    get { return (GetRuleViolations().Cast<RuleViolation>().Count() == 0); }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.