2013-04-03 76 views
15

Làm thế nào tôi có thể tích hợp các phương pháp .DefaultIfEmpty() mở rộng vì vậy tôi có không sử dụngSử dụng .DefaultIfEmpty() thay vì .FirstOrDefault() ?? String.Empty;

.FirstOrDefault() ?? String.Empty; 

Code:

(from role in roleList 
let roleArray = role.RoleId.Split(new char[] { WorkflowConstants.WorkflowRoleDelimiter }) 
where roleArray.Length.Equals(_SplittedRoleIdArrayLength) && 
     HasAccessToCurrentUnit(roleArray[_UnitIndexInRoleId]) 
select roleArray[_LevelIndexInRoleId]).FirstOrDefault() ?? String.Empty; 
+2

Cá nhân tôi thì không. 'DefaultIfEmpty' quan tâm đến số đếm, không phải giá trị vô hướng. Tạo phương thức mở rộng của riêng bạn, có thể được đặt tên cũng là 'FirstOrDefault' lấy đối số' T' để chỉ định làm mặc định. –

Trả lời

12

Bạn có thể sử dụng:

var query = ...; 

return query.DefaultIfEmpty(string.Empty).First(); 

Nhưng điều này không giảm IMO phức tạp.

+0

Việc giảm độ phức tạp là một trong những mục tiêu của tôi. Bất kỳ đề xuất nào khác cho đến nay bạn có? – Elisabeth

+1

Xin chào, ông 2k. Bây giờ bạn đang trong thực tế 14k! –

+0

Tôi đã chuyển sang giải pháp của bạn. – Elisabeth

7

Nếu bạn quan tâm đến phương pháp khuyến nông sau đó bạn có thể sử dụng một cái gì đó như thế này:

public static class Helpers 
{ 
    public static string FirstOrEmpty(this IEnumerable<string> source) 
    { 
     return source.FirstOrDefault() ?? string.Empty; 
    } 
} 

Sửa

Phương pháp này là không chung vì sau đó chúng ta sẽ phải sử dụng default(T) và nó sẽ cung cấp cho chúng tôi null thay vì string.Empty.

+1

có thể sau đó 'T FirstOrEmpty (nguồn IEnumerable này)' –

+1

@Ilya Ivanov, nếu nó sẽ là chung chung thì nó mặc định vẫn sẽ là null cho chuỗi. –

+1

Nhưng 'T FirstOrDefault (nguồn IEnumerable nguồn, T mặc định)' sẽ là có thể. Sau đó, một lần nữa, '.FirstOrDefault (string.Empty)' so với '.irstOrDefault() ?? string.Empty' không thực sự tạo ra nhiều sự khác biệt. – hvd

1

Mã:

var query=(
    from role in roleList 
    let delimiter=WorkflowConstants.WorkflowRoleDelimiter 
    let roleArray=role.RoleId.Split(new char[] { delimiter }) 
    where roleArray.Length.Equals(_SplittedRoleIdArrayLength) 
    where HasAccessToCurrentUnit(roleArray[_UnitIndexInRoleId]) 
    select roleArray[_LevelIndexInRoleId] 
    ).DefaultIfEmpty("").FirstOrDefault(); 

Đối với sự nghi ngờ về ý nghĩa ngữ nghĩa của DefaultIfEmptyFirstOrDefault, sau là mã decompiled từ thư viện:

  • public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source) 
    { 
        return source.DefaultIfEmpty<TSource>(default(TSource)); 
    } 
    
    public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, TSource defaultValue) 
    { 
        if (source == null) 
        { 
         throw Error.ArgumentNull("source"); 
        } 
        return DefaultIfEmptyIterator<TSource>(source, defaultValue); 
    } 
    
    public static TSource First<TSource>(this IEnumerable<TSource> source) 
    { 
        if (source == null) 
        { 
         throw Error.ArgumentNull("source"); 
        } 
        IList<TSource> list = source as IList<TSource>; 
        if (list != null) 
        { 
         if (list.Count > 0) 
         { 
          return list[0]; 
         } 
        } 
        else 
        { 
         using (IEnumerator<TSource> enumerator = source.GetEnumerator()) 
         { 
          if (enumerator.MoveNext()) 
          { 
           return enumerator.Current; 
          } 
         } 
        } 
        throw Error.NoElements(); 
    } 
    
    public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source) 
    { 
        if (source == null) 
        { 
         throw Error.ArgumentNull("source"); 
        } 
        IList<TSource> list = source as IList<TSource>; 
        if (list != null) 
        { 
         if (list.Count > 0) 
         { 
          return list[0]; 
         } 
        } 
        else 
        { 
         using (IEnumerator<TSource> enumerator = source.GetEnumerator()) 
         { 
          if (enumerator.MoveNext()) 
          { 
           return enumerator.Current; 
          } 
         } 
        } 
        return default(TSource); 
    } 
    

Và đây là cái gì đó để đề cập đến:

  1. DefaultIfEmpty có một tình trạng quá tải parameterless, mà gọi sự quá tải tham số với default(TSource) và trả về kết quả của nó.

  2. Sự khác biệt duy nhất giữa parameterless FirstOrDefaultFirst, là tùy chọn thứ hai sẽ ném khi bộ sưu tập trống.

    Để biết thêm thông tin, hãy xem Enumerable.FirstOrDefault<TSource> Method trên MSDN.

  3. FirstOrDefault ngữ nghĩa biểu thị first or default và được gọi là; nó không có tên là first or null. Trong C#, default(T) cho loại tham chiếu là null, nhưng đối với loại không tham chiếu, không phải loại tham chiếu. Ví dụ: default(int) bằng không.

    Từ khóa default chưa bao giờ được nói null ngữ nghĩa. Đó là DEFAULT.

    Ngoài ra, để biết thêm thông tin, default Keyword trên MSDN.

+1

Your FirstOrDefault(); ở cuối không có ý nghĩa gì cả. Nếu bạn mong đợi một giá trị null bằng OrDefault thì trình tự của bạn trống. Sau đó, "" sẽ được trả lại ... Tôi đề nghị. Đầu tiên() thay thế. – Elisabeth

+0

@Elisa: Vâng, chúng giống nhau ở đây, vì tôi chỉ sao chép từ mã của bạn và không thay đổi, nhưng tôi nghĩ điều đó không quan trọng. –

+0

Nó cũng quan trọng. Sử dụng FirstOrDefault chỉ 50%. Các OrDefault (giá trị null) sẽ không bao giờ xảy ra và cung cấp cho người đọc một ấn tượng sai về những gì mã đang làm. – Elisabeth

2

Tôi tìm thấy khóa học này về PluralSight thú vị và tôi nhớ khi tôi nhìn thấy câu hỏi này.

Bạn có thể xem toàn bộ khóa học, nhưng các chiến lược Map Reduce và Option<T> đặc biệt với DefaultIfEmpty dường như có thể phù hợp với trường hợp sử dụng của bạn.

Tactical Design Patterns trong .NET: Flow Control bởi Zoran Horvat https://app.pluralsight.com/library/courses/tactical-design-patterns-dot-net-control-flow/table-of-contents

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