2010-02-23 17 views
13

¿Hay una mejor manera de conseguir el primer elemento de tipo IEnumerable de esto:¿Cómo obtener el primer elemento de IEnumerable

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

Ésta es la declaración exacta del tipo:

public class ImageList : IEnumerable, IDisposable 
+0

¿Por qué no utiliza el 'IEnumerable ' genérico 'así' ImageList' podría derivarse de 'IEnumerable '? –

+1

@Arnis: porque ImageLIst defien en la biblioteca de ImageMagick.net ... :) –

Respuesta

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

@Mark, se requiere Cast ... no podemos usar simplemente "var firstImage = ImgList.First()" ?? – RameshVel

+4

@Ramesh: se requiere 'Cast 'en este caso ya que' First' se implementa para 'IEnumerable ' pero 'ImageList' solo implementa' IEnumerable'. –

+1

@Ramesh Vel, no puede usar imgList.First() ya que no es un IEnumerable genérico antes de emitirlo. – JonC

5

La extensión .First() tomará el primer elemento de un enumerable. Si la colección está vacía, lanzará una excepción. .FirstOrDefault() devolverá un valor predeterminado para una colección vacía (nulo para los tipos de referencia). ¡Elige tu arma sabiamente!

10

Si no puede utilizar LINQ también se puede obtener el empadronador directamente por imgList.GetEnumerator() y luego hacer un .MoveNext() para pasar al primer elemento. .Current le dará el primer elemento.

0

podría ser ligeramente irrelevante para su situación actual, pero también hay un .Single() y una .SingleOrDefault() que devuelve el primer elemento y se produce una excepción si no es exactamente un elemento de la colección (.Single()) o si hay más de un elemento en la colección (.SingleOrDefault()).

Estos pueden ser muy útiles si tienes una lógica que depende de que solo haya un objeto (o cero) en tu lista. Aunque sospecho que no son lo que querías aquí.

+0

En realidad, conozco a Linq muy bien, pero el 'IEnumerable' era confuso ya que trabajo regularmente con' IEnumerable '. –

0

Tuve un problema donde cambié mi fuente de datos de un bindingsource a una consulta de entidad de marco.

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

Con entidad framework esto arroja una excepción `No se pudo convertir el tipo 'cliente' para escribir 'objeto'. LINQ to Entities solo admite la conversión de primitiva EDM o tipos de enumeración.

La clase donde estaba mi código no tenía una referencia a la lib con el modelo así que ...Cast<customer> no fue posible.

De todos modos he usado este enfoque

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

en conjunción con una extensión IEnumerable que utiliza la reflexión

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(); 
    } 

dude en implementar el almacenamiento en caché según el tipo para mejorar el rendimiento.

Cuestiones relacionadas