IEnumberable к тому, что я могу получить граф? - PullRequest
0 голосов
/ 21 июля 2009

У меня есть это:

private IEnumerable _myList;

Мне нужно отсчитать этот объект. Ранее я набирал _myList в массив и получал длину, но теперь мы используем этот же бит кода с другим типом объекта. Это по-прежнему тип Collection (это строго типизированный объект Subsonic Collection), и все прекрасно работает, за исключением того, что нам нужно получить общее количество элементов в объекте.

Я пытался набрать его в CollectionBase и многих других типах, но ничего не работает, что не позволило бы мне получить .Count или .Length или что-то в этом роде.

Кто-нибудь может указать мне правильное направление?

РЕДАКТИРОВАТЬ: я не использую 3.5, я использую 2. Таким образом, все, что связано с Linq не будет работать. Извините, что не опубликовал это ранее.

Ответы [ 9 ]

11 голосов
/ 21 июля 2009

Это на самом деле IEnumerable вместо IEnumerable<T>? Если это так, LINQ не поможет вам напрямую. (Вы можете использовать Cast<T>(), как предложено в другом месте, но это будет относительно медленно - в частности, оно не будет оптимизировано для IList / IList<T> реализаций.)

Предлагаю вам написать:

public static int Count(this IEnumerable sequence)
{
    if (sequence == null)
    {
        throw new ArgumentNullException("sequence");
    }

    // Optimisation: won't optimise for collections which
    // implement ICollection<T> but not ICollection, admittedly.
    ICollection collection = sequence as ICollection;
    if (collection != null)
    {
        return collection.Count;
    }

    IEnumerator iterator = sequence.GetEnumerator();
    try
    {
        int count = 0;
        while (iterator.MoveNext())
        {
            // Don't bother accessing Current - that might box
            // a value, and we don't need it anyway
            count++;
        }
        return count;
    }
    finally
    {
        IDisposable disposable = iterator as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }
}
10 голосов
/ 21 июля 2009

Метод расширения System.Linq.Enumerable.Count делает это для напечатанного IEnumerable<T>. Для нетипизированного IEnumerable попробуйте сделать собственное расширение:

    public static int Count(this IEnumerable source)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        ICollection collectionSource = source as ICollection;
        if (collectionSource != null)
        {
            return collectionSource.Count;
        }

        int num = 0;
        IEnumerator enumerator = source.GetEnumerator();
        //try-finally block to ensure Enumerator gets disposed if disposable
        try
        {
            while (enumerator.MoveNext())
            {
                num++;
            }
        }
        finally
        {
            // check for disposal
            IDisposable disposableEnumerator = enumerator as IDisposable;
            if(disposableEnumerator != null)
            {
                disposableEnumerator.Dispose();
            }
        }
        return num;
    }
4 голосов
/ 21 июля 2009

Если вы используете .NET 3.5, вы можете использовать Enumerable.Count () , чтобы получить счет от любого IEnumerable<T>.

Это не сработает от неуниверсального IEnumerable, однако - для этого требуется IEnumerable<T>.

Это должно работать, так как классы коллекций Subsonic реализуют подходящие интерфейсы для вас. Вам нужно изменить определение с IEnumerable на IEnumerable<MyClass>.

1 голос
/ 21 июля 2009

Тип, который вы используете - IEnumerable, который не имеет свойства Count. Но общий эквивалент, IEnumerable (T), имеет свойство Count.

Очевидным решением является использование IEnumerable (T), но если вы не можете, вы можете сделать что-то вроде этого:

_myList.Cast<MyListItemType>().Count()

Приведение - это простой способ конвертировать IEnumerable в IEnumerable (SomeType), но, очевидно, это не лучший способ получить счетчик производительности.

Если производительность является фактором, я бы просто перебрал значения, чтобы получить счетчик, если только вы не знаете, что базовая коллекция имеет свойство Count (см. Ответ Джона Скита ...).

1 голос
/ 21 июля 2009

Если вы включите пространство имен System.Linq, IEnumerable<T> имеет метод расширения Count () . Вы можете написать свой собственный метод расширения, чтобы получить его в неуниверсальной версии. Обратите внимание, что этот метод будет блокировать типы значений, поэтому, если это может привести к проблемам с производительностью, выберите решение Джона Скита Это просто проще.

public static int Count(this IEnumerable enumerable)
{
    int count = 0;
    foreach(object item in enumerable)
    {
        count++;
    }
    return count;
}
1 голос
/ 21 июля 2009

LINQ предоставляет метод расширения Count().

using System.Linq;

...

var count = _myList.Count();
0 голосов
/ 11 августа 2010

Мне нужно то же самое, и я создал IEnumerableList. Причина заключалась в том, что мне не нравилось оценивать каждый раз, когда мне нужно подсчет через весь перечисляемый объект, как это делается с помощью метода расширения Count ().

Подробнее об этом здесь: http://fknet.wordpress.com/2010/08/11/string-formatwith-extension/

0 голосов
/ 21 июля 2009

Если базовый объект реализует ICollection, вы можете использовать свойство .Count ().

0 голосов
/ 21 июля 2009

Как насчет звонка .ToList()?

...