Как получить первый элемент IEnumerable - PullRequest
16 голосов
/ 23 февраля 2010

Есть ли лучший способ получить первый элемент типа IEnumerable этого:

foreach (Image image in imgList)
{
     picture.Width = (short)image.Columns;
     picture.Height = (short)image.Rows;
     break;
}

Это точное объявление типа:

public class ImageList : IEnumerable, IDisposable

Ответы [ 5 ]

31 голосов
/ 23 февраля 2010
var firstImage = imgList.Cast<Image>().First();
10 голосов
/ 23 февраля 2010

Если вы не можете использовать LINQ, вы также можете получить счетчик напрямую по imgList.GetEnumerator() А затем выполните .MoveNext(), чтобы перейти к первому элементу. .Current даст вам первый элемент.

5 голосов
/ 23 февраля 2010

Расширение .First() захватит первый элемент в перечислимом. Если коллекция пуста, она выдаст исключение. .FirstOrDefault() вернет значение по умолчанию для пустой коллекции (ноль для ссылочных типов). Выбери свое оружие с умом!

0 голосов
/ 07 сентября 2017

У меня возникла проблема, когда я изменил свой источник данных с источника привязки на запрос структуры сущности.

var query = dataSource as IQueryable;
var value = query.Where("prop = @0", value).Cast<object>().SingleOrDefault();

В рамках сущности это создает исключение `Невозможно привести тип 'customer' к типу 'object'. LINQ to Entities поддерживает только приведение типов примитивов и перечислений EDM.

Класс, в котором был мой код, не имел ссылки на библиотеку с моделью, поэтому ...Cast<customer> был невозможен.

В любом случае, я использовал этот подход

var query = dataSource as IQueryable;
var targetType = query.GetType().GetGenericArguments()[0];
var value = query.Where("prop = @0", value).SingleOrDefault(targetType);

в сочетании с расширением IEnumerable, которое использует отражение

    public static object SingleOrDefault(this IEnumerable enumerable, Type type)
    {
        var method = singleOrDefaultMethod.Value.MakeGenericMethod(new[] { type });
        return method.Invoke(null, new[] { enumerable });
    }

    private static Lazy<MethodInfo> singleOrDefaultMethod 
         = new Lazy<MethodInfo>(() =>
             typeof(Extensions).GetMethod(
                 "SingleOrDefault", BindingFlags.Static | BindingFlags.NonPublic));

    private static T SingleOrDefault<T>(IEnumerable<T> enumerable)
    {
        return enumerable.SingleOrDefault();
    }

Не стесняйтесь внедрять кэширование для каждого типа для повышения производительности.

0 голосов
/ 23 февраля 2010

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

Это может быть очень полезно, если у вас есть логика, которая зависит от наличия только одного (или нуля) объектов в вашем списке. Хотя я подозреваю, что это не то, что вы хотели здесь.

...