7

问题很简单

是这个代码

public Dictionary<string, SomeObject> values = new Dictionary<string, SomeObject>();

void Function()
{
    values["foo"].a = "bar a";
    values["foo"].b = "bar b";
    values["foo"].c = "bar c";
    values["foo"].d = "bar d";
}

和这段代码一样快

public Dictionary<string, SomeObject> values = new Dictionary<string, SomeObject>();

void Function()
{
    var someObject = values["foo"];
    someObject.a = "bar a";
    someObject.b = "bar b";
    someObject.c = "bar c";
    someObject.d = "bar d";
}

常识告诉我,在字典中查找一次引用并将其存储在某个地方应该更快,这样就不需要多次查找,但我真的不知道字典是如何工作的。

那么它是否更快?为什么?

4

3 回答 3

7

是的,你是对的。您的第一种方法执行字典查找 4 次,而第二种方法执行一次。第二个肯定更好。

然而,在现实生活中,字典查找速度快得离谱,所以除非你有一个庞大的字典,否则差异不会很明显,甚至可能无法测量。

于 2013-03-15T15:05:24.937 回答
6

乔是绝对正确的,但好像还不够我做了一个简单的明显测试:

static void Main(string[] args)
{
    var dict = new Dictionary<string, Foo>();
    var number = 10000000;
    for (int i = 0; i < number; i++)
    {
        dict[i.ToString()] = new Foo();
    }

    var watch = new Stopwatch();

    watch.Start();
    for (int i = 0; i < number; i++)
    {
        var key = i.ToString();
        dict[key].A = "a";
        dict[key].B = "b";
        dict[key].C = "c";
        dict[key].D = "d";
    }

    watch.Stop();
    Console.Out.WriteLine(watch.ElapsedMilliseconds);

    watch.Reset();

    watch.Start();
    for (int i = 0; i < number; i++)
    {
        var key = i.ToString();
        var foo = dict[key];

        foo.A = "a";
        foo.B = "b";
        foo.C = "c";
        foo.D = "d";
    }

    watch.Stop();
    Console.Out.WriteLine(watch.ElapsedMilliseconds);
}   

class Foo
{
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
    public string D { get; set; }
}

在我的机器上,这输出到:

3423
2113
Press any key to continue . . .

只有 1 次查找肯定会减少大数字的总时间。

于 2013-03-15T15:37:59.813 回答
1

我很好奇。以下单元测试(可能)表明第二种方法快了大约 25%。(121 毫秒对 91 毫秒)。从 6 个字段到 2 个字段缩小了差距,分别为 40 毫秒和 33 毫秒。我说可能是因为我写得很快,而且我不相信它不会测量一些副作用,但它显示了预期的行为,所以为什么要质疑它。(哈)。

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;

namespace TestProject1
{

public class DataObject
{
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
    public string D { get; set; }
    public string E { get; set; }
    public string F { get; set; }
}

[TestClass]
public class UnitTest1
{
    public static Dictionary<string, DataObject> dict = new Dictionary<string, DataObject>();
    static string lookie;

    [ClassInitialize()]
    public static void MyClassInitialize(TestContext testContext) {

        Random rand = new Random(123545);
        for (int i = 0; i < 10000; i++)
        {
            string key = rand.NextDouble().ToString();
            DataObject dob = new DataObject();
            dict.Add(key, dob);
            if (i == 4567)
                lookie = key;
        }

    }


    [TestMethod]
    public void TestMethod()
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int j = 0; j < 100000; j++)
        {
            dict[lookie].A = "val" + j;
            dict[lookie].B = "val" + j;
            dict[lookie].C = "val" + j;
            dict[lookie].D = "val" + j;
            dict[lookie].E = "val" + j;
            dict[lookie].F = "val" + j;
        }
        sw.Stop();

        System.Diagnostics.Debug.WriteLine(sw.ElapsedMilliseconds);

        sw.Reset();
        sw.Start();
        for (int j = 0; j < 100000; j++)
        {
            DataObject dob = dict[lookie];
            dob.A = "val" + j;
            dob.B = "val" + j;
            dob.C = "val" + j;
            dob.D = "val" + j;
            dob.E = "val" +j;
            dob.F = "val" +j;
        }
        sw.Stop();

        System.Diagnostics.Debug.WriteLine(sw.ElapsedMilliseconds);
    }
  }
}
于 2013-03-15T15:32:47.830 回答