【发布时间】:2011-01-28 06:12:08
【问题描述】:
我在 Enumerable.cs 中通过反射器发现了这个实现。
public static TSource Single<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
//check parameters
TSource local = default(TSource);
long num = 0L;
foreach (TSource local2 in source)
{
if (predicate(local2))
{
local = local2;
num += 1L;
//I think they should do something here like:
//if (num >= 2L) throw Error.MoreThanOneMatch();
//no necessary to continue
}
}
//return different results by num's value
}
我认为如果有两个以上的项目满足条件,他们应该打破循环,为什么他们总是循环整个集合?万一那个反射器错误地反汇编了dll,我写了一个简单的测试:
class DataItem
{
private int _num;
public DataItem(int num)
{
_num = num;
}
public int Num
{
get{ Console.WriteLine("getting "+_num); return _num;}
}
}
var source = Enumerable.Range(1,10).Select( x => new DataItem(x));
var result = source.Single(x => x.Num < 5);
对于这个测试用例,我认为它会打印“getting 0, getting 1”然后抛出异常。但事实是,它一直在“得到 0...得到 10”并抛出异常。 他们这样实现这个方法有什么算法原因吗?
EDIT你们中的一些人认为是因为谓词表达式的副作用,经过深思熟虑和一些测试用例,我有一个结论side在这种情况下效果并不重要。如果您不同意这个结论,请举例说明。
【问题讨论】:
-
@The Smartest:看看我的“手动”解码为 C#
-
@The Smartest:你应该改用 First 或 FirstOrDefault,我相信这是 BCL 编写者所期望的
-
先生。疯狂地回答了这个问题并否决了所有答案......
-
Enumerable.cs 是 System.Linq 的一部分,它位于 System.Core.dll 中,是 BCL 的一部分。这个库是在许可许可下发布的还是专有的?我相信(但我不是 100% 确定)它是专有的。请不要发布专有代码 - 阅读此内容的人不能为 Mono 等项目做出贡献。
-
@Michael:这不是基于 MS-RSL 许可证,而是基于二进制文件。事实上,即使是这样,它也无关紧要:无论它有什么条款都是被许可人的合同条款——而不是诸如 mono 之类的第三方——他们很可能甚至没有任何许可证。考虑到范围、改写和选择以及微小的范围——很难说这是相关的。我严重怀疑 mono 和 microsoft 是否会在法庭上基于一个明显、微不足道且非常短的算法的非专利实现而在法庭上面对面,所以我们不要在这里得意忘形......