0

我首先运行了以下代码:

var stringList = new[]{"A","BB","CCC","DDDD"};
var dictionary = new Dictionary<int, string>();
var stopwatch = new Stopwatch();
stopwatch.Start();
foreach (var s in stringList)
{
    dictionary.Add(s.Length,s);
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);
Console.ReadKey();

执行时间为:00:00:00.0000205

然后我运行了以下代码...

var stringList = new[]{"A","BB","CCC","DDDD"};
var stopwatch = new Stopwatch();
stopwatch.Start();
var dictionary = stringList.ToDictionary(s => s.Length);
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);
Console.ReadKey();

执行时间为:00:00:00.0037431

这是否证明 foreach 比 LINQ 更好?

4

4 回答 4

2

是不是证明foreach比LINQ好??

不,它证明它更快。

更好是一个主观的概念。例如,如果您希望拥有更易读和更紧凑的代码,并且性能不是项目的首要任务,并且确定这不是瓶颈,那么 LINQ 实际上可能会更好。

于 2013-04-25T08:12:04.923 回答
2

您的示例有几处错误:

  • 样本量很小。数组中有四个元素??尝试 1,000,000
  • 在第一个示例中,字典对象是在秒表之外创建的。对象创建是速度的一个因素,特别是对于这样一个小例子
  • LINQ 代码使用委托。诚然,这是 LINQ 中的常见用法,但要获得真正的比较,要么两者都应该使用方法,要么都应该使用委托。

你应该查看 Jon Skeet关于这个主题的博客文章

于 2013-04-25T08:19:11.170 回答
2

您可以看到ToDictionary使用 .NET 源代码或 ILSpy 的真实外观:

public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (keySelector == null)
    {
        throw Error.ArgumentNull("keySelector");
    }
    if (elementSelector == null)
    {
        throw Error.ArgumentNull("elementSelector");
    }

    Dictionary<TKey, TElement> dictionary = new Dictionary<TKey, TElement>(comparer);
    foreach (TSource current in source)
    {
        dictionary.Add(keySelector(current), elementSelector(current));
    }
    return dictionary;
}

如您所见,它也使用foreach!然而,参数检查和Func委托使得它比你的自定义代码效率低一点,只Dictionary.Add需要方法调用。但是,我认为在实际应用中,使用而不是自定义的惩罚并不重要。ToDictionaryforeach

于 2013-04-25T08:19:55.633 回答
0

为什么?

因为没有魔法,LINQ 版本比非 LINQ 版本做了很多处理。

我写了一小段代码来展示 LINQ 在内部做什么。你可以看到几乎相同的表演。还要注意我在循环中添加了字典的实例化:

int testCount = 1000000;
var stringList = new[] { "A", "BB", "CCC", "DDDD" };

Func<string, string> elementSelector = (value) => value;

var stopwatch = Stopwatch.StartNew();

for (int i = 0; i < testCount; i++)
{
    var dictionary = new Dictionary<int, string>();
    Func<string, int> keySelector = (value) => value.Length;
    foreach (var s in stringList)
    {
        if (keySelector != null && elementSelector != null)
        {
            dictionary.Add(keySelector(s), elementSelector(s));
        }
    }
}

stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed.TotalMilliseconds / testCount);

var stopwatch2 = Stopwatch.StartNew();

for (int i = 0; i < testCount; i++)
{
    var dictionary2 = stringList.ToDictionary(s => s.Length);
}

stopwatch2.Stop();
Console.WriteLine(stopwatch2.Elapsed.TotalMilliseconds / testCount);

Console.ReadKey();
于 2013-04-25T08:29:04.917 回答