我有一个高级程序,它从数据库中检索数据,并通过C#中的ExpandoObjects从数据中创建对象。
我现在正在优化我的整个过程,但遇到了一段代码,这是性能方面的瓶颈。我很好奇我可以在多大程度上优化这段代码,并且通过执行以下操作已经设法以3倍的速度运行它:
添加了一个值为null的情况并创建一个空字符串,因为由于某种原因,在添加Null值时,Dictionary.Add会减慢很多。
// Holds all objects that are created inside the object.
Dictionary<string, IDictionary<string, dynamic>> objects = new Dictionary<string, IDictionary<string, dynamic>>();
// This foreach loop is the slowest part!
foreach (KeyValuePair<string, dynamic> pair in fields)
{
string type = pair.Key.Split('_')[0];
IDictionary<string, dynamic> obj;
if (!objects.TryGetValue(type, out obj))
{
obj = new ExpandoObject();
objects.Add(type, obj);
}
int location = pair.Key.IndexOf(type + "_");
string key = pair.Key.Remove(location, type.Length + 1);
if (pair.Value == null) // If Value is null, replace it with an empty string (dictionary slows quite alot when passing it null values)
obj.Add(key, "");
else
obj.Add(key, pair.Value);
}
if (types == null)
types = objects.Select(x => x.Key).ToList();
我很想知道,在添加Null值时,字典是如何减慢的呢?是否在底层结构中遇到空值时会执行特殊操作?是否有一些我缺少进一步优化代码的东西?。
再次非常感谢任何帮助。
<小时/> 的更新
答案 0 :(得分:2)
您可以使用TryGetValue
代替ContainsKey
来避免字典中的多次查找:
foreach (KeyValuePair<string, dynamic> pair in fields)
{
string type = pair.Key.Split('_')[0];
IDictionary<string, dynamic> obj;
if (!objects.TryGetValue(type, out obj))
{
obj = new ExpandoObject();
objects.Add(type, obj);
}
int location = pair.Key.IndexOf(type + "_");
string key = pair.Key.Remove(location, type.Length + 1);
if (pair.Value == null)
obj.Add(key, "");
else
obj.Add(key, pair.Value);
}
BTW:我没有看到你在第二个types
循环中使用foreach
。因此,您可以使用以下简单代码替换第一个 foreach
循环:
types = objects.Select(x => x.Key).ToList();
这可以节省相当多的时间,因为它删除了types
列表中的慢速搜索和类型的双重解析。
显然,这需要在我上面显示的foreach
循环之后进行。