我正在向StringDictionary添加项目,并且可能会出现重复的密钥.这当然会抛出异常.
如果重复的可能性非常低(即很少发生),我最好使用Try Catch块并使其处理不当,或者在添加每个条目之前是否应该总是进行.ContainsKey检查?
我假设如果重复密钥的可能性很高,那么允许异常将是一个糟糕的决定,因为它们很昂贵.
思考?
编辑
我在泛型字典中使用了反射器,并为ContainsKey和TryGetValue找到了以下内容,因为两者都在下面提到.
public bool TryGetValue(TKey key, out TValue value)
{
int index = this.FindEntry(key);
if (index >= 0)
{
value = this.entries[index].value;
return true;
}
value = default(TValue);
return false;
}
Run Code Online (Sandbox Code Playgroud)
和
public bool ContainsKey(TKey key)
{
return (this.FindEntry(key) >= 0);
}
Run Code Online (Sandbox Code Playgroud)
我错过了什么,或者TryGetValue比ContainsKey做更多的工作?
我很欣赏这些回复,对于我目前的目的,我将继续做一个ContainsKey调用,因为集合很小,而且代码更具可读性.
Fre*_*örk 16
如何处理这取决于发生碰撞时您想要做什么.如果要保留第一个插入的值,则应ContainsKey在插入之前进行检查.另一方面,如果要使用该键的最后一个值,则可以这样做:
// c# sample:
myDictionary[key] = value;
Run Code Online (Sandbox Code Playgroud)
作为旁注:如果可能的话,我可能会使用Dictionary<string, string>而不是StringDictionary.如果没有别的东西可以让你访问更多的Linq扩展方法.
我会做包含检查.
我的理由是应该为那些不应该发生的事情保存例外.如果他们这样做,那么应该响起警报铃声并引入调用.对于我来说,对于已知问题案例处理使用例外情况似乎很奇怪,尤其是当您可以测试它时.
我对此做了一些基准测试。但我必须重申凯尔西的观点:
应该为那些不应该发生的事情保存异常。如果他们这样做了,那么应该敲响警钟并引入髑髅。对我来说,使用异常处理已知问题案例似乎很奇怪,尤其是当您可以对其进行测试时。
这是有道理的,因为你通过追求try-catch(如果有的话)获得的性能提升是微不足道的,但“捕获”可能会更加不利。这是测试:
public static void Benchmark(Action method, int iterations = 10000)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < iterations; i++)
method();
sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
}
public static string GetRandomAlphaNumeric()
{
return Path.GetRandomFileName().Replace(".", "").Substring(0, 8);
}
var dict = new Dictionary<string, int>();
Run Code Online (Sandbox Code Playgroud)
Benchmark(() =>
{
// approach 1
var key = GetRandomAlphaNumeric();
if (!dict.ContainsKey(key))
dict.Add(item, 0);
// approach 2
try
{
dict.Add(GetRandomAlphaNumeric(), 0);
}
catch (ArgumentException)
{
}
}, 100000);
Run Code Online (Sandbox Code Playgroud)
for (int i = 0; i < 50000; i++)
{
dict.Add(GetRandomAlphaNumeric(), 0);
}
var lst = new List<string>();
for (int i = 0; i < 50000; i++)
{
lst.Add(GetRandomAlphaNumeric());
}
lst.AddRange(dict.Keys);
Benchmark(() =>
{
foreach (var key in lst)
{
// approach 1
if (!dict.ContainsKey(key))
dict.Add(key, 0);
// approach 2
try
{
dict.Add(key, 0);
}
catch (ArgumentException)
{
}
}
}, 1);
Run Code Online (Sandbox Code Playgroud)
var key = GetRandomAlphaNumeric();
dict.Add(key, 0);
Benchmark(() =>
{
// approach 1
if (!dict.ContainsKey(key))
dict.Add(item, 0);
// approach 2
try
{
dict.Add(key, 0);
}
catch (ArgumentException)
{
}
}, 100000);
Run Code Online (Sandbox Code Playgroud)
结果:
没有重复
方法 1:调试 -> 630 毫秒 - 680 毫秒;释放 -> 620 毫秒 - 640 毫秒
方法 2:调试 -> 640 毫秒 - 690 毫秒;释放 -> 640 毫秒 - 670 毫秒
50% 重复
方法 1:调试 -> 26 毫秒 - 39 毫秒;释放 -> 25 毫秒 - 33 毫秒
方法 2:调试 -> 1340 毫秒;释放 -> 1260 毫秒
100% 重复
方法 1:调试 -> 7 毫秒;释放 -> 7 毫秒
方法 2:调试 -> 2600 毫秒;释放 -> 2400 毫秒
您可以看到,随着重复次数的增加,try-catch表现不佳。即使在根本没有重复项的最坏情况下, 的性能增益try-catch也没有任何实质性的提升。
如果可能的话,更换StringDictionary用Dictionary<string, string>,并使用TryGetValue.这避免了异常处理开销和双重查找.
| 归档时间: |
|
| 查看次数: |
22577 次 |
| 最近记录: |