2010-02-23 32 views
13

Có cách nào tốt hơn nhận được phần tử đầu tiên của loại IEnumerable điều này:Làm thế nào để có được những yếu tố đầu tiên của IEnumerable

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

Đây là tuyên bố chính xác của các loại:

public class ImageList : IEnumerable, IDisposable 
+0

Tại sao bạn không sử dụng chung 'IEnumerable 'do đó' ImageList' có thể lấy được từ' IEnumerable '? –

+1

@Arnis: vì ImageLIst defien trong thư viện ImageMagick.net ... :) –

Trả lời

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

@Mark, là Cast cần thiết .. chúng tôi không thể sử dụng "var firstImage = ImgList.First()" ?? – RameshVel

+4

@Ramesh: 'Cast' là bắt buộc trong trường hợp này vì' First' được triển khai cho 'IEnumerable ' nhưng 'ImageList' chỉ thực hiện' IEnumerable'. –

+1

@Ramesh Vel, bạn không thể sử dụng imgList.First() vì nó không phải là một chung IEnumerable trước khi đúc nó. – JonC

5

Tiện ích mở rộng .First() sẽ lấy mục đầu tiên trong một số đếm. Nếu bộ sưu tập trống, nó sẽ ném một ngoại lệ. .FirstOrDefault() sẽ trả lại giá trị mặc định cho một bộ sưu tập trống (không cho các loại tham chiếu). Chọn vũ khí của bạn một cách khôn ngoan!

10

Nếu bạn không thể sử dụng LINQ, bạn cũng có thể nhận điều tra trực tiếp bằng cách imgList.GetEnumerator() Và sau đó thực hiện .MoveNext() để chuyển sang phần tử đầu tiên. .Current sau đó sẽ cung cấp cho bạn phần tử đầu tiên.

0

Có thể là hơi không liên quan đến tình hình hiện tại của bạn, nhưng đó cũng là một .Single().SingleOrDefault() mà trả về phần tử đầu tiên và ném một ngoại lệ nếu không có đúng một phần tử trong bộ sưu tập (.Single()) hoặc nếu có nhiều hơn một phần tử trong bộ sưu tập (.SingleOrDefault()).

Đây có thể rất hữu ích nếu bạn có logic phụ thuộc vào chỉ có một đối tượng đơn lẻ (hoặc không) trong danh sách của bạn. Mặc dù tôi nghi ngờ họ không phải là những gì bạn muốn ở đây.

+0

Thực ra tôi biết LINQ rất tốt, nhưng 'IEnumerable' là khó hiểu vì thường xuyên làm việc với' IEnumerable '. –

0

Tôi gặp sự cố trong đó tôi đã thay đổi nguồn dữ liệu của mình từ một bindingsource thành truy vấn khung thực thể.

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

Với khung thực thể, trường hợp này ném ngoại lệ 'Không thể nhập' khách hàng 'để nhập' đối tượng '. LINQ to Entities chỉ hỗ trợ đúc các kiểu nguyên thủy hoặc liệt kê EDM.

Lớp mà mã của tôi không có tham chiếu đến lib với mô hình vì vậy ...Cast<customer> là không thể.

Dù sao tôi đã sử dụng phương pháp này

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

kết hợp với một phần mở rộng IEnumerable trong đó sử dụng phản ánh

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

cảm thấy tự do để thực hiện bộ nhớ đệm cho mỗi loại để cải thiện hiệu suất.

Các vấn đề liên quan