Ответ 1
var firstImage = imgList.Cast<Image>().First();
Есть ли лучший способ получить первый элемент типа IEnumerable:
foreach (Image image in imgList)
{
picture.Width = (short)image.Columns;
picture.Height = (short)image.Rows;
break;
}
Это точная декларация типа:
public class ImageList : IEnumerable, IDisposable
var firstImage = imgList.Cast<Image>().First();
Если вы не можете использовать LINQ, вы также можете получить перечисление непосредственно imgList.GetEnumerator()
Затем сделайте .MoveNext()
, чтобы перейти к первому элементу.
.Current
затем предоставит вам первый элемент.
Расширение .First()
будет захватывать первый элемент в перечислимом. Если коллекция пуста, она выдает исключение. .FirstOrDefault()
вернет значение по умолчанию для пустой коллекции (null для ссылочных типов). Выберите свое оружие мудро!
Может быть, немного не имеет отношения к вашей текущей ситуации, но есть также .Single()
и .SingleOrDefault()
, которые возвращают первый элемент и выдает исключение, если в коллекции не содержится ровно один элемент (.Single()
). или если в коллекции имеется более одного элемента (.SingleOrDefault()
).
Это может быть очень полезно, если у вас есть логика, которая зависит только от наличия единственного (или нулевого) объекта в вашем списке. Хотя я подозреваю, что они не то, что вы хотели здесь.
У меня возникла проблема, когда я сменил свой источник данных с источника привязки на запрос структуры сущности.
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();
}
не стесняйтесь реализовать кэширование для каждого типа, чтобы повысить производительность.