您更愿意看到什么?
try
{
var item = list.Single(x => x.HasFoo);
}
catch(InvalidOperationException e)
{
throw new InvalidOperationException("Exactly one item with foo expected, none found", e);
}
或者:
var item = list.SingleOrDefault(x => x.HasFoo);
if (item == null)
throw new InvalidOperationException("Exactly one item with foo expected, none found");
这里的最佳做法是什么?哪一个让异常更容易理解?
答案 0 :(得分:79)
SingleOrDefault()
Single()
另请注意,有许多可能的情况:
和
不要忘记First()
,FirstOrDefault()
和Any()
答案 1 :(得分:5)
我会写:
var item = list.Single(x => x.HasFoo);
如果这不会返回单个项目的情况如此常见,您需要更友好的错误消息,那么它真的是一个例外吗?
答案 2 :(得分:4)
实际上,它们是一样的。但是我更喜欢第二个,因为在前两个中引发了一个异常。 例外情况很昂贵。
答案 3 :(得分:3)
我认为写
是可以的var item = list.SingleOrDefault(x => x.HasFoo);
if (item == null) ...
但你也可以写
if (list.Any(x => x.HasFoo)) ...
如果您实际上不需要访问该值。
答案 4 :(得分:2)
如果您总是预测列表中的一个元素,请使用
var item = list.Single(x => x.HasFoo);
并在顶级方法中捕获异常,您将在其中记录异常的详细信息并向用户显示友好消息。
如果您有时期望0或超过1个元素,最安全的方法将是
var item = list.FirstOrDefault(x => x.HasFoo);
if (item == null)
{
// empty list processing, not necessary throwing exception
}
我认为,验证并不重要,是否存在超过1条记录。
中讨论了类似的问题答案 5 :(得分:1)
在获取元素之前,我宁愿看一下列表中元素的数量,而不是等待异常,然后再抛出一个新元素。
var listFiltered = list.Where(x => x.HasFoo).ToList();
int listSize = listFiltered.Count();
if (listSize == 0)
{
throw new InvalidOperationException("Exactly one item with foo expected, none found");
}
else if (listSize > 1)
{
throw new InvalidOperationException("Exactly one item with foo expected, more than one found");
}
建议很紧凑很好,但最好是更明确的IMO。
(同样在你的建议中,例外不是严格有效的:当可能有多个时,他们说“没有找到”)
编辑:Jeebus,为迂腐的人添加了一行来过滤列表。 (我认为这对任何人来说都是显而易见的)
答案 6 :(得分:1)
假设您询问 0..1 方案,我更喜欢 SingleOrDefault ,因为它允许您指定自己的方式来处理“无法找到”方案。< / p>
因此,使用少量语法糖的好方法是:
// assuming list is List<Bar>();
var item = list.SingleOrDefault(x => x.HasFoo) ?? notFound<Bar>();
其中notFound()是:
T notFound<T>()
{
throw new InvalidOperationException("Exactly one item with foo expected, none found");
}
答案 7 :(得分:0)
我同意基伦·约翰斯通的观点,不要等待这个非常昂贵的例外情况,当你多次调用这种方法时确定。
你的第一个代码片段更贵,因为你等待原来的异常,而不是给自己一个新的。
答案 8 :(得分:0)
<强>单强>
它返回元素集合中的单个特定元素if 找到元素匹配。抛出异常,如果没有或多于一个 在集合中找到该元素的匹配项。
<强>的SingleOrDefault 强>
它返回元素集合中的单个特定元素if 找到元素匹配。如果有多个匹配,则抛出异常 在集合中找到该元素。返回默认值, 如果没有找到该集合中该元素的匹配项。
这是示例: -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqSingleorSingleOrDefault
{
class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
}
public class Program
{
static void Main(string[] args)
{
IList<Employee> employeeList = new List<Employee>(){
new Employee() { Id = 10, Name = "Chris", City = "London" },
new Employee() { Id=11, Name="Robert", City="London"},
new Employee() { Id=12, Name="Mahesh", City="India"},
new Employee() { Id=13, Name="Peter", City="US"},
new Employee() { Id=14, Name="Chris", City="US"}
};
//Single Example
var result1 = employeeList.Single();
// this will throw an InvalidOperationException exception because more than 1 element in employeeList.
var result2 = employeeList.Single(e => e.Id == 11);
//exactly one element exists for Id=11
var result3 = employeeList.Single(e => e.Name == "Chris");
// throws an InvalidOperationException exception because of more than 1 element contain for Name=Chris
IList<int> intList = new List<int> { 2 };
var result4 = intList.Single();
// return 2 as output because exactly 1 element exists
//SingleOrDefault Example
var result5 = employeeList.SingleOrDefault(e => e.Name == "Mohan");
//return default null because not element found for specific condition.
var result6 = employeeList.SingleOrDefault(e => e.Name == "Chris");
// throws an exception that Sequence contains more than one matching element
var result7 = employeeList.SingleOrDefault(e => e.Id == 12);
//return only 1 element
Console.ReadLine();
}
}
}