如何获得IEnumerable的第一个元素

时间:2010-02-23 09:49:32

标签: c# .net ienumerable linq-to-objects html-lists

是否有更好的方法来获取IEnumerable类型的第一个元素:

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

这是类型的确切声明:

public class ImageList : IEnumerable, IDisposable

5 个答案:

答案 0 :(得分:30)

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

答案 1 :(得分:10)

如果你不能使用LINQ,你也可以通过imgList.GetEnumerator()直接获取枚举器 然后执行.MoveNext()移动到第一个元素。 .Current然后会给你第一个元素。

答案 2 :(得分:5)

扩展程序.First()将获取可枚举中的第一项。如果集合为空,则会抛出异常。 .FirstOrDefault()将返回空集合的默认值(引用类型为null)。明智地选择你的武器!

答案 3 :(得分:0)

可能与您当前的情况略有不相关,但还有一个.Single()和一个.SingleOrDefault()返回第一个元素,如果集合中没有一个元素,则会抛出异常( .Single())或者集合中有多个元素(.SingleOrDefault())。

如果您的逻辑仅依赖于列表中的单个(或零)对象,则这些非常有用。虽然我怀疑他们不是你想要的。

答案 4 :(得分:0)

我遇到了一个问题,我将数据源从绑定源更改为实体框架查询。

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

使用实体框架会抛出异常“无法转换类型&#39;客户&#39;键入&#39; object&#39;。 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();
    }

随意实现每种类型的缓存以提高性能。