Как получить первый элемент IEnumerable

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

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

Это точная декларация типа:

public class ImageList : IEnumerable, IDisposable

Ответы

Ответ 1

var firstImage = imgList.Cast<Image>().First();

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

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

С фреймворком сущности это генерирует исключение "Невозможно наложить тип" клиент "на тип" объект ". LINQ to Entities поддерживает только листинг EDM примитивных или перечисляемых типов.

Класс, в котором мой код не имел ссылки на lib с моделью, поэтому ...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();
    }

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