字典对象的性能表现

3
我有一个可能需要用到字典对象的实现场景,该对象将接受3个变量,分别为方言、查询名称和查询字符串。需要注意的是,在此阶段编写单独的类对象不是一种选择。
我的问题是以下哪种实现方式性能更好。
A) 单一字典对象,将前两个变量作为组合键,如“方言,查询名称”,第三个变量作为值。
private Dictionary<string, string>

B) 一个字典对象,其值为另一个字典对象,因此第一个变量将是主字典对象的键,第二个变量将是第二个字典对象的键,最后一个变量将是第二个字典对象的值。

private Dictionary<string, Dictionary<string, string>>

看起来很显而易见,但编译器是一件神秘的东西,所以我想问问你们。

谢谢


IDictionary<string, IDictionary<string, string>> dic = new Dictionary<string, Dictionary<string, string>> - abatishchev
我很好奇 - 为什么不考虑编写另一个类? - Tim Lloyd
4个回答

2
只要你确定“dialect,queryname”键是唯一的,我认为第一个解决方案更快。在第二个解决方案中,你需要进行一次额外的字典查找,这可能比字符串连接更昂贵。

是的,我百分之百确定这些键将是完全唯一的。那是我的想法,但我想确认一下。谢谢回复。 - CSharpened

2

只是为了自己的娱乐而胡闹..


涉及IT技术,仅供参考。

             Dictionary<string, string> md1 = new Dictionary<string,string>();
             Dictionary<string, Dictionary<string, string>> md2 = new Dictionary<string, Dictionary<string, string>>();

             Stopwatch st = new Stopwatch();

             st.Start(); 

             for (int i = 0; i < 2000000; i++)
             {
                 md1.Add(i.ToString(), "blabla"); 
             }

             st.Stop();

             Console.WriteLine(st.ElapsedMilliseconds);

             st.Reset();

             st.Start(); 

             for (int i = 0; i < 2000000; i++)
             {
                 md2.Add(i.ToString(), new Dictionary<string, string>()); 
             }

             st.Stop();

             Console.WriteLine(st.ElapsedMilliseconds);

             Console.ReadLine(); 

输出:

831
1399

1
不错。但是你只是在测试对象的创建,而不是数据检索。 - Kevin Gosse
是的没错。不过你可以很容易地计时检索。 - Yorak Hunt

0
为什么不使用以下代码:
Dictionary<string, KeyValuePair<string, string>>

我认为这比两者都更好。


1
你可以在.NET 4.0中使用Tuple<string,string> - abatishchev

0

这不是性能问题,因为两者具有完全不同的语义。

第一个提供了一种使用一个对象查找另一个对象的方法。

第二个提供了一种使用一个对象查找另一个对象的方法,在其中可以使用另一个对象查找第三个对象。

在后续扩展方面,它们的功能略有不同。

通常情况下,我会使用 Dictionary<Tuple<string, string>, string>。这将给我一个明显是复合键的复合键。

实际上,那不是真的,我会创建一个新类。为什么不选这个选项呢?但如果这是作业,并且“不要创建新类”是问题的一部分,我会使用 Dictionary<Tuple<string, string>, string>

编辑:

class DialectQuery : IEquatable<DialectQuery>
{
  public Dialect{get;private set}
  public Name{get;private set;}
  public DialectQuery(string dialect, string name)
  {
    Dialect = dialect;
    Name = name;
  }
  public bool Equals(DialectQuery other)
  {
    return other != null && Name == other.Name && Dialect == other.Dialect;
  }
  public override bool Equals(object other)
  {
    return Equals((object)other);
  }
  public override int GetHashCode()
  {
    int dHash = Dialect.GetHashCode();
    return (dHash << 16 | dHash >> 16) ^ Name.GetHashCode();
  }
}

到目前为止,它的行为与元组完全相同。但是,如果我收到一个更改请求,要求方言不区分大小写但查询名称区分大小写,或者方言是代码,因此需要不变比较,但名称是人类输入,因此需要文化感知比较,或者其他任何事情,我只需进行两个简单的更改。

YAGNI并不适用于这种情况,它不是在编写一个大型对象“以防万一”,而是定义了一个良好的“好吧,我可能不需要它,但如果需要,它将放在这里”的点。


如果您要使用一个类,您会如何构建它以便能够在保持相同功能的同时产生相同或更好的性能?我需要能够构造它并用来自数据库表中的所有三个变量(每个变量不止一个)填充它,然后能够快速地使用两个关键变量提取查询字符串。对我来说,使用我提到的第一种选项似乎要简单得多。 - CSharpened
作为一个简单的类,它有两个属性和一个相等性重载。这只需要半分钟的编码,但可以很好地处理“哦,方言应该不区分大小写,但查询不应该”或者在规范下游出现的任何其他扩展。 - Jon Hanna
这对我的情况确切地如何运作?如果我需要有效地生成一个可以通过两个键访问的SQL命令列表,那该怎么办?我想使用字典对象的原因是,一旦填充了所有必要的方言、查询名称和查询,当我实例化我的SQL工厂类时,我可以通过检查复合键来访问任何我需要的查询。可能只是我大脑运转缓慢,但我看不出如何使用类来做到这一点?所有三个变量都像这样链接:方言>查询名称>查询。你怎么用属性来做到这一点? - CSharpened

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接