Linq中的 First 和 Single 在實際工作中會經??吹?,從字面意思上很容易明白,一個是取列表中的第一個元素,一個是取到唯一的元素。如果你想再進一步的了解,可以讀讀本文。
下文參考翻譯自:
C#/.NET Little Wonders: First() and Single() - Similar Yet Different
First() - 返回序列中的第一個元素
事實上這個方法有四種選擇:
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
新聞熱點
疑難解答