2009-05-27 100 views

回答

12

比试图用文字解释更好,我想我只是在.NET Framework中发布实现的确切代码,使用Reflector程序检索(并重新格式化)。

public static TSource SingleOrDefault<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) 
     throw Error.ArgumentNull("source"); 

    IList<TSource> list = source as IList<TSource>; 
    if (list != null) 
    { 
     switch (list.Count) 
     { 
      case 0: 
       return default(TSource); 
      case 1: 
       return list[0]; 
     } 
    } 
    else 
    { 
     using (IEnumerator<TSource> enumerator = source.GetEnumerator()) 
     { 
      if (!enumerator.MoveNext()) 
       return default(TSource); 

      TSource current = enumerator.Current; 
      if (!enumerator.MoveNext()) 
       return current; 
     } 
    } 

    throw Error.MoreThanOneElement(); 
} 

这是相当有趣的oberserve,如果对象是IList<T>类型,它看起来非常明智的优化而成。它简单地回退到枚举对象,否则如果对象实现的任何东西都不比IEnumerable<T>更具体,并且这样做只是你的期望。

请注意,它不能使用二分查找,因为该对象不一定表示已排序的集合。 (实际上,在几乎所有使用情况下,都不会)。

0

我不认为它做了任何搜索,它都是关于获取源[list,result set等]的第一个元素。

我最好的猜测是它只是拉第一个元素。如果没有第一个,它将返回默认值(null,0,false等)。如果有第一个,它试图拉第二个结果。如果有第二个结果,则会引发异常。否则它返回第一个结果。

2

我假设它只是执行查询,如果结果计数为零,它将返回该类的默认实例。如果结果数为1,则返回该实例,如果结果数大于1,则会引发异常。