c#如何取字典表的值_C#中关于字典(Dictionary)的使用
字典的取值常用的取值方法有2种:方法1:先判断是否存在,如果存在再进行取值if(aDictionary.ContainsKey(key)){var value = Dictionary[key];}int value;aDictionary.TryGetValue(key, out value);项目中,如果只是要取值,推荐使用TryGetValue来获取。原因:方法1中ContainsKey执行
字典的取值
常用的取值方法有2种:
方法1:先判断是否存在,如果存在再进行取值if(aDictionary.ContainsKey(key))
{
var value = Dictionary[key];
}int value;
aDictionary.TryGetValue(key, out value);
项目中,如果只是要取值,推荐使用TryGetValue来获取。
原因:
方法1中ContainsKey执行了一次方法,Dictionary[key]再次执行了一次方法,整个取值过程调用了2次方法。而方法2的TryGetValue只调用了一次方法。当然并不是调用的方法越多越耗性能,看源码后就能理解。
方法1:
public bool ContainsKey(TKey key) {
return FindEntry(key) >= 0;
}
//Dictionary[key]取值原理
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);
}
}
方法2:
public bool TryGetValue(TKey key, out TValue value)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
lock(_lock)
{
VerifyIntegrity();
return TryGetValueWorker(key, out value);
}
}
private bool TryGetValueWorker(TKey key, out TValue value)
{
int entryIndex = FindEntry(key);
if (entryIndex != -1)
{
Object primary = null;
Object secondary = null;
_entries[entryIndex].depHnd.GetPrimaryAndSecondary(out primary, out secondary);
// Now that we've secured a strong reference to the secondary, must check the primary again
// to ensure it didn't expire (otherwise, we open a ---- where TryGetValue misreports an
// expired key as a live key with a null value.)
if (primary != null)
{
value = (TValue)secondary;
return true;
}
}
value = default(TValue);
return false;
}
通过源码可以看到,这几个方法都获取值都要通过FindEntry(key)来实现
private int FindEntry(TKey key)
{
int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue;
for (int entriesIndex = _buckets[hashCode % _buckets.Length]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next)
{
if (_entries[entriesIndex].hashCode == hashCode && _entries[entriesIndex].depHnd.GetPrimary() == key)
{
return entriesIndex;
}
}
return -1;
}
可以看出通过key来获取HashCode,然后通过equal比对值,字典存储中会给key一个对应的hashcode,如果数据过多,那么hashCode也可能重复,所以需要进行比较。时间主要花费在这上面。
那么结论显而易见,如果只是取值,直接用TryGetValue花费更小,更快速,更安全,找不到value时返回false;
在通过一个测试代码来验证时间的花费:
public class TestDictionary
{
static void Main(string[] args)
{
Dictionary test = new Dictionary { { "a", "b"} ,{ "a2","b2"} };
string x;
var start = DateTime.Now;
for (int i = 0; i != 10000000; i++)
{
test.TryGetValue("c", out x);
test.TryGetValue("b", out x);
}
Console.WriteLine(DateTime.Now - start);
//-------------------------------------
start = DateTime.Now;
for (int i = 0; i != 10000000; i++)
{
if (test.ContainsKey("c"))
{
x = test["a"];
}
if (test.ContainsKey("b"))
{
x = test["a2"];
}
}
Console.WriteLine(DateTime.Now - start);
Console.ReadLine();;
}
}
查找不存在的值时花费时间几乎相同
查找的值存在时,可以看出时间接近2倍
另外在提一下关于Keys的,因为在字典中键值对是成对存储的,使用keys会单独拿出所有的key来组成一个关于Key的数组,会产生额外的CG,如果不是要单独对keys进行处理,推荐少用这个。
用Unity自带的Profile来进行测试
public class test : MonoBehaviour
{
Dictionary testd = new Dictionary { { "a", null }, { "a2", "b2" } };
bool t = false;
// Update is called once per frame
void Update()
{
//让其只执行一次
if (!t) {
Nokeys();
Keys();
t = true;
}
}
//直接对字典进行迭代
void Nokeys() {
foreach (var key in testd)
{
Dosomething(key.Key);
}
}
//对Keys进行迭代
void Keys()
{
foreach (var key in testd.Keys) {
Dosomething(key);
}
}
void Dosomething(string key) { }
}
调用Keys方法时
未调用Keys方法
更多推荐


所有评论(0)