2009-05-04 31 views
32

SingleOrDefault trả về null, nhưng nếu tôi muốn gán giá trị đại diện cho đối tượng không được tìm thấy thì sao?SingleOrDefault: Làm thế nào để thay đổi các giá trị mặc định?

+0

bạn có tìm thấy câu trả lời nào không? bạn không thể thay đổi mặc định là lời hứa theo phương thức. vì SingleOrDefault phải là SingleOrNull nhưng nó có thể trả về đối tượng giá trị. ai có thể trả về 0 cho int, đó là số mặc định hoặc số được cho là? SingleOrDefault có thể trả về 0 nhưng không được mặc định. trả về null hay không. đó là mô hình xấu cho OOP. –

Trả lời

5

Bạn có thể tự cuộn.

public static T SingleOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) { 
    if (1 != enumerable.Count()) { 
    return defaultValue; 
    } 
    return enumerable.Single(); 
} 

Điều này có thể tốn kém một chút do Count() yêu cầu bạn xử lý toàn bộ bộ sưu tập và có thể tốn kém để chạy. Sẽ tốt hơn cho một trong hai gọi Độc thân, bắt InvalidOperationException hoặc cuộn một phương pháp IsSingle

public static bool IsSingle<T>(this IEnumerable<T> enumerable) { 
    using (var e = enumerable.GetEnumerator()) { 
    return e.MoveNext() && !e.MoveNext(); 
    } 
} 

public static T SingleOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) { 
    if (!enumerable.IsSingle()) { 
    if(enumerable.IsEmpty()) { 
     return defaultValue; 
    } 
    throw new InvalidOperationException("More than one element"); 
    } 
    return enumerable.Single(); 
} 
+1

Điều này sẽ trả về giá trị mặc định nếu có thể đếm được nhiều đối tượng. Không nên nó ném một ngoại lệ như việc thực hiện tiêu chuẩn không? – tvanfosson

+0

@tvanfosson đúng vậy. Tôi đã có ấn tượng rằng SingleOrDefault sẽ trả về giá trị mặc định nếu có bất kỳ điều gì khác ngoài một phần tử. Nhưng rõ ràng nó sẽ chỉ làm như vậy cho không có yếu tố. Lạ thật, tôi sẽ cập nhật. – JaredPar

52

bạn có thể làm một cái gì đó giống như

myStrings.DefaultIfEmpty("myDefaultString").Single() 

séc ra here

+0

Cách tiếp cận khác nhau +1 – ichiban

+3

+1 để dạy tôi một phương pháp mới – ajbeaven

0

Bạn có thể tạo ra phương pháp khuyến nông của riêng bạn - SingleOrNew.

public static class IEnumerableExtensions 
{ 
    public static T SingleOrNew<T>(this IEnumerable<T> enumeration, T newValue) 
    { 
     T elem = enumeration.SingleOrDefault(); 
     if (elem == null) 
     { 
      return newValue; 
     } 
     return elem; 
    } 

    public static T SingleOrNew<T>(this IEnumerable<T> enumeration, Func<T,bool> predicate, T newValue) 
    { 
     T elem = enumeration.SingleOrDefault(predicate); 
     if (elem == null) 
     { 
      return newValue; 
     } 
     return elem; 
    } 
} 
+3

Vấn đề với phương pháp này là bạn sẽ trả về tham số newValue cho một tập hợp chứa một phần tử có giá trị null. Xem xét biểu thức này (chuỗi mới [] {null}). SingleOrNew ("foo") ;. Nó sẽ trả lại không chính xác "foo" – JaredPar

+0

@JaredPar - tôi sẵn sàng sống với điều đó. Nói chung, tôi không đặt null trong bộ sưu tập của tôi và tôi đã tìm thấy một khi sử dụng một phương pháp như thế này, tôi có lẽ muốn thay thế nó với giá trị mặc định của tôi anyway. – tvanfosson

+1

@tvanfosson, đó là một thay đổi đột phá đáng kể từ thuật toán ban đầu mà làm cho một giả định khổng lồ về cách mọi người sử dụng null. – JaredPar

24

?? operator. Nếu đối số bên trái là null, đánh giá và trả về đối số thứ hai.

myCollection.SingleOrDefault() ?? new[]{new Item(...)} 

Điều này sẽ chỉ hoạt động với các loại tham chiếu (hoặc null), nhưng nó sẽ làm những gì bạn đang tìm kiếm rất đơn giản.

+3

Một tràng pháo tay nhỏ xuất hiện trong đầu tôi khi tôi sử dụng sự kết hợp rỗng. +1 – Stimul8d

+0

@ Joe Tôi nghĩ rằng OP thực sự muốn thay đổi giá trị mặc định được trả về trực tiếp từ SingleOrDefault(), ví dụ: nếu tìm kiếm đối tượng Person và không tồn tại đối tượng nào thì có thể anh ta muốn SingleOrDefault() trả về một đối tượng NullPerson. Sự hiểu biết của tôi là không thể thay đổi kiểu trả về và vấn đề phải được giải quyết theo cách bạn đã làm, nhưng một lần nữa tôi nghĩ điều quan trọng là phải làm rõ cho OP rằng giá trị trả về mặc định của SingleOrDefault() không thể đã thay đổi. – Matt

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