Fra*_*dal 15 linq collections linq-to-sql
每当我拿这样的东西时,我都会收到异常
Feature f = o.Features.SingleOrDefault(e => e.LinkName == PageLink);
Run Code Online (Sandbox Code Playgroud)
因为这可以返回一个或多个元素.我可以用什么替代方法来解决这个问题?
spe*_*der 29
Single和SingleOrDefault设计为在序列中存在多于一个匹配时抛出.其结果是必须在完成之前迭代整个序列.听起来这不是你想要的.请尝试使用FirstOrDefault:
Feature f = o.Features
.FirstOrDefault(e => e.vcr_LinkName == PageLink && e.bit_Activate == true);
Run Code Online (Sandbox Code Playgroud)
这将(通常)执行得更好,因为一旦找到匹配就完成.
当然,如果您确实想要保留多个元素,那么Where子句会更合适:
IEnumerable<Feature> fs = o.Features
.Where(e => e.vcr_LinkName == PageLink && e.bit_Activate == true);
Run Code Online (Sandbox Code Playgroud)
Pie*_*kel 21
或者,如果你只想要一个匹配的项目,并且当有多个匹配时不想抛出,那么这很容易实现.我在我的项目中为此创建了一个扩展方法:
public static class QueryableExtensions
{
public static TSource SingleWhenOnly<TSource>(this IQueryable<TSource> source)
{
if (source == null)
throw new ArgumentNullException("source");
var results = source.Take(2).ToArray();
return results.Length == 1 ? results[0] : default(TSource);
}
public static TSource SingleWhenOnly<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
if (source == null)
throw new ArgumentNullException("source");
if (predicate == null)
throw new ArgumentNullException("predicate");
var results = source.Where(predicate).Take(2).ToArray();
return results.Length == 1 ? results[0] : default(TSource);
}
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 14
如果您只想要第一个元素,请FirstOrDefault
改用.
基本上,以下是有效结果的选项(即您不想扔的地方)以及使用的内容:
Single
SingleOrDefault
First
FirstOrDefault
(ElementAt
和ElementAtOrDefault
,Last
并且LastOrDefault
也可提供.)
我发现如果不存在一个比正常SingleOrDefault
行为更多的元素(即零个,两个或更多个),我需要返回默认值的行为,所以这是我的Pieter van Ginkel的改编版本:
public static class LinqExtensions
{
/// <summary>
/// Returns the only element of a sequence, or a default value if the sequence is empty or contains more than one element.
/// </summary>
public static TSource SingleOrDefaultIfMultiple<TSource>(this IEnumerable<TSource> source)
{
var elements = source.Take(2).ToArray();
return (elements.Length == 1) ? elements[0] : default(TSource);
}
/// <summary>
/// Returns the only element of a sequence, or a default value if the sequence is empty or contains more than one element.
/// </summary>
public static TSource SingleOrDefaultIfMultiple<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
return source.Where(predicate).SingleOrDefaultIfMultiple();
}
/// <summary>
/// Returns the only element of a sequence, or a default value if the sequence is empty or contains more than one element.
/// </summary>
public static TSource SingleOrDefaultIfMultiple<TSource>(this IQueryable<TSource> source)
{
var elements = source.Take(2).ToArray();
return (elements.Length == 1) ? elements[0] : default(TSource);
}
/// <summary>
/// Returns the only element of a sequence, or a default value if the sequence is empty or contains more than one element.
/// </summary>
public static TSource SingleOrDefaultIfMultiple<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
return source.Where(predicate).SingleOrDefaultIfMultiple();
}
}
Run Code Online (Sandbox Code Playgroud)
我省略了null参数检查,因为在参数为null时我可以依靠Take
and Where
调用引发异常,但是您可能会感到不舒服。