C# 中奇妙的函數 — 2. First 和 Single — 你是她心中的第一還是唯一?

來源:互聯網
上載者:User

Linq中的 First 和 Single 在實際工作中會經常看到,從字面意思上很容易明白,一個是取列表中的第一個元素,一個是取到唯一的元素。如果你想再進一步的瞭解,可以讀讀本文。

下文參考翻譯自: C#/.NET Little Wonders: First() and Single() - Similar Yet DifferentFirst() - 返回序列中的第一個元素

事實上這個方法有四種選擇:

  • First()

    • 返回序列中的第一個,如果沒有元素存在就拋出異常 InvalidOperationException.
  • First(Predicate<TSource>)
    • 基於你提供的條件返回序列中的第一個,如果沒有元素存在就拋出異常 InvalidOperationException.
  • FirstOrDefault()
    • 返回序列中的第一個,如果沒有元素存在就返回預設的元素default(TSource).
  • FirstOrDefault(Predicate<TSource>)
    • 基於你提供的條件返回序列中的第一個,如果沒有元素存在就返回預設的元素default(TSource).

First的核心思想是如果序列中存在一個以上元素的時候,就返回第一個。這也意味著當發現第一個元素的時候,被調用的這個方法就立刻退出了不會再去遍曆尋找剩下的元素了。

舉例看看,定義一個類:

  public sealed class Employee {     public long Id { get; set; }     public string Name { get; set; }     public double Salary { get; set; } }

給他一些初始化的列表:有空的,一個元素的,多個元素的

 // 空表var noEmployeeList = new List<Employee>(); // 一個元素var oneEmployeeList = new List<Employee>    {        new Employee { Id = 55, Name = "Sussie Queue", Salary = 60000.50 }    }; // 多個元素var employees = new List<Employee>    {        new Employee { Id = 1, Name = "Jim Smith", Salary = 12345.50 },        new Employee { Id = 7, Name = "Jane Doe", Salary = 31234.50 },        new Employee { Id = 9, Name = "John Doe", Salary = 13923.99 },        new Employee { Id = 13, Name = "Jim Smith", Salary = 30123.49 },                // ... etc ...    };

好,當我們使用First的時候,他們會有什麼結果呢?

 var first = employees.First();var firstJohn = employees.First(e => e.Name.StartsWith("John"));var firstDoe = employee.First(e => e.Name.EndsWith("Doe"));

另外請注意在下面的情況下會拋出異常:

 var empty = noEmployees.First();var noMatch = employees.First(e => e.Id == 20);

最後,當我們使用帶有Default的方法時,下面的情況會返回空值而不是拋出異常:

 var empty = noEmployees.FirstOrDefault();var noMatch = employees.FirstOrDefault(e => e.Id == 20);

Single() – 有且僅有一個

 像First一樣,Single 也有四種表現形式:

  • Single()
    • 返回序列中的唯一的元素,如果沒有元素存在就拋出異常 InvalidOperationException, 如果多於一個,也拋出異常InvalidOperationException.
  • Single(Predicate<TSource>)
    • 基於你提供的條件返回序列中的唯一的元素,如果沒有元素存在就拋出異常 InvalidOperationException, 如果多於一個,拋出異常InvalidOperationException.  SingleOrDefault()
  • SingleOrDefault()
  • 返回序列中的唯一的元素,如果沒有元素存在就返回預設的元素default(TSource), 如果多於一個,拋出異常InvalidOperationException.
  • SingleOrDefault(Predicate<TSource>)
    • 基於你提供的條件返回序列中的唯一的元素,如果沒有元素存在就返回預設的元素default(TSource), 如果多於一個,拋出異常InvalidOperationException.
  • 請注意,關鍵的區別主要在這裡: 如果有一個以上的元素,這個家族的方法會永遠拋出InvalidOperationException異常。  還要注意,這意味著,即使Single 方法得到了一個匹配的元素,它仍然有可能要掃描其餘的枚舉。 這可以使 Single 效率要低一點。

    下面一些例子返回什麼呢?

     var oneAndOnly = oneEmployeeList.Single();var throwsOnEmpty = noEmployeeList.Single();var throwsOnMultiple = employeeList.Single();

    從下面的例子,我們看到Single 和 First 的相似性, 不同的在於滿足結果的序列多於一個元素的情況

     // 得到 ID == 7 的唯一元素var oneAndOnlyMatch = oneEmployeeList.Single(e => e.Id == 7); // 拋出異常var throwsOnNoMatches = noEmployeeList.Single(e => e.Id == 999); // 拋出異常var throwsOnMultipleMatches = employeeList.Single(e => e.Name.EndsWith("Doe"));// 返回一個null的元素.var defaultsOnEmpty = noEmployeeList.SingleOrDefault(); // 返回一個null的元素.var defaultsOnNoMatch = noEmployeeList.SingleOrDefault(e => e.Id == 999);

    結論

    First 和 Single 都有一個避免當沒有元素滿足要求而拋出異常的選擇,當你不確定想要擷取的元素是否存在的時候,可以用…OrDefault(), 因為 null 可以很好的表示“找到不”。

    當你不在乎是否有重複項目或者不可能有重複元素存在的時候,可以使用First; 當你想要核實是否有重複元素存在的時候當然就選擇Single。

    謝謝你閱讀本文,更多.NET話題請到:

    喜樂的ASP.NET

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.