C# ContainsKey與TryGetValue方法探究


最近在進行在做一個鏈路選擇的需求,涉及到字典存儲。發現C#的Dictionary提供了ContainsKey和TryGetValue兩個方法,都可以來判斷字典中是否存在對應的Key值。那么這兩個方法有什么區別呢?我們在編寫代碼的過程中如何選取呢?

我先創建了一個Dictionary<string, int>的字典,然后從0遞增到一千萬分別給這個字典添加了數據。

static Dictionary<string, int> dic = new Dictionary<string, int>();
const int TOTALNUM = 10000000;

for (int i = 0; i < TOTALNUM; i++)
{
    dic.Add(i.ToString(), i);
}

我們借助StopWatch,對ContainsKey和TryGetValue分別進行一千萬次的查找,比較兩者所花費的時間。

Stopwatch stopwatch1 = new Stopwatch(); // TryGetValue
Stopwatch stopwatch2 = new Stopwatch(); // COntainsKey

測試環境:

  • IDE工具:VS2019
  • CPU:i7-8700
  1. 當取出的Value在執行過程中有被使用時:

    stopwatch1.Start();
    long a = 0;
    for (int i = 0; i < TOTALNUM; i++)
    {
        string str = i.ToString();
        if (dic.TryGetValue(str, out var value))
        {
            // Value被使用
            a = a + value;
        }
    }
    stopwatch1.Stop();
    
    stopwatch2.Start();
    long b = 0;
    for (int i = 0; i < TOTALNUM; i++)
    {
        string str = i.ToString();
        if (dic.ContainsKey(str))
        {
            // Value被使用
            b = b + dic[str];
        }
    }
    stopwatch2.Stop();
    

    ContainsKey所花費的時間較多

  2. 當沒有對字典所對應Key的Value進行操作時:

    ...
        if (dic.TryGetValue(str, out var value))
        {
            a = a + 1;
        }
    ...
    
    ...
        if (dic.ContainsKey(str))
        {
            b = b + 1;
        }
    ...
    

    TryGetValue花費的時間更多

  3. 查看源碼:

    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;
    }
    
    public bool ContainsKey(TKey key)
    {
        return (this.FindEntry(key) >= 0);
    }
    
    
    public TValue this[TKey key] 
    {
    	get 
        {
        	int i = FindEntry(key);
            if (i >= 0) return entries[i].value;
            ThrowHelper.ThrowKeyNotFoundException();
            return default(TValue);
        }
        set 
        {
        	Insert(key, value, false);
        }
    }
    

    查看源碼我們發現TryGetValue是在ContainsKey的基礎上直接從存儲中取出Value。有一個很關鍵的函數FindEntry我們在三個函數都有看到,說明我們如果在使用完ContainsKey在用Dic[Key]去取值的時候,會多一次開銷。

總結

  • 在數據量不大的情況下,兩者並沒有太大的差別。在數據量大的情況下,如果對Value並沒有操作推薦用ContainsKey,反之則使用TryGetValue。當Key的命中率遠低於50%,且操作Value時,也可以考慮使用ContainsKey。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM