C# 中的字典与哈希表

本指南将讨论 C# 中 DictionaryHashtable 之间的区别。

要了解这些集合中哪个更好和更受欢迎,我们需要了解它们的基本原理。那么,让我们来看看与这两个集合相关的语法、特征、功能和方法。

在使用 C# 时,你应该更喜欢哪一个?哪个更好?

所有这些问题都将在下面得到解答。让我们潜入吧!

C# 中的字典

Dictionary 是一个通用集合。它将数据存储在键值对中,并且这个集合没有特定的顺序。

字典的语法如下:

Dictionary<TKey, TValue>

我们将数据值连同它们的键一起传递。让我们来看看字典的特点。

C# 中字典的特征

  1. 它存储键值对。
  2. 它的命名空间是 System.Collections.Generic
  3. Dictionary 中的键不能为空并且应该是唯一的。
  4. 但是,值可以为空值和重复值。
  5. 我们可以通过其对应的键访问数据值,例如,myDictionary[key]
  6. 所有元素都被认为是 KeyValuePair<TKey, TValue>

C# 中创建字典

你可以通过传递值的类型及其可以存储的相应键在 C# 中创建一个字典。查看以下代码,了解我们如何创建 Dictionary

IDictionary<int, string> rollno_names = new Dictionary<int, string>();
rollno_names.Add(1,"Ali"); //adding a key/value using the Add() method
rollno_names.Add(2,"Haider");
rollno_names.Add(3,"Saad");
//The following throws runtime exception: key already added.
//rollno_names.Add(3, "Rafay");
foreach(KeyValuePair<int, string> i in rollno_names)
    Console.WriteLine("Key: {0}, Value: {1}", i.Key, i.Value);
//creating a dictionary using collection-initializer syntax
var countries = new Dictionary<string, string>(){
    {"UK", "United Kingdom"},
    {"USA", "United States of America"},
    {"PK", "Pakistan"}
};
foreach(var j in countries)
    Console.WriteLine("Key: {0}, Value: {1}", j.Key, j.Value);

在上面的代码中,rollno_names 是一个 Dictionary,其中 int 为键数据类型,字符串为值数据类型,如下所示:

Dictionary<int, string>

这个特殊的 Dictionary 可以存储 int 键和字符串值。第二个字典是由集合初始化器创建的国家/地区。

它的键和值都是字符串数据类型。如果你尝试复制键值并将其设置为 null,你将获得运行时异常。

C# 中访问字典元素

你可以在索引器的帮助下访问 Dictionary 元素。你需要指定每个键来访问其对应的值。

ElementAt() 是另一种获取键值对的方法。看看下面的代码。

var countries= new Dictionary<string, string>(){
    {"UK", "UnitedKingdom"},
    {"USA", "United State of America"},
    {"PK", "Pakistan"}
};
Console.WriteLine(countries["UK"]); //prints value of UK key
Console.WriteLine(countries["USA"]);//prints value of USA key
//Console.WriteLine(countries["France"]); // runtime exception: key does not exist
//use ContainsKey() to check for the unknown key
if(countries.ContainsKey("France")){
    Console.WriteLine(countries["France"]);
}
//use TryGetValue() to get a value of the unknown key
string result;
if(countries.TryGetValue("France", out result))
{
    Console.WriteLine(result);
}
//use ElementAt() to retrieve the key-value pair using the index
for (int i = 0; i < countries.Count; i++)
{
    Console.WriteLine("Key: {0}, Value: {1}",
             countries.ElementAt(i).Key,
             countries.ElementAt(i).Value);
}

在上面的代码中,你可以看到没有包含 France 的键值对。所以,上面的代码会给出一个运行时异常。

C# 中更新字典元素

通过在索引器中指定键,可以更改/更新键的值。如果在 Dictionary 中没有找到键,它将抛出 KeyNotFoundException 异常;因此,在访问任何未知键之前使用 ContainsKey() 函数。

看看下面的代码。

var countries= new Dictionary<string, string>(){
    {"UK", "London, Manchester, Birmingham"},
    {"USA", "Chicago, New York, Washington"},
    {"PK", "Pakistan"}
};
countries["UK"] = "Europe"; // update value of UK key
countries["USA"] = "America"; // update value of USA key
//countries["France"] = "Western Europe"; //throws run-time exception: KeyNotFoundException
if(countries.ContainsKey("France")){
    countries["France"] = "Western Europe";
}

C# 中删除字典元素

使用 Remove() 方法删除 Dictionary 中已经存在的键值对。使用 Clear() 方法删除所有 Dictionary 元素。

var countries= new Dictionary<string, string>(){
    {"UK", "UnitedKingdom"},
    {"USA", "United state of America"},
    {"PK", "Pakistan"}
};
countries.Remove("UK"); // removes UK
//countries.Remove("France"); //throws run-time exception: KeyNotFoundException
if(countries.ContainsKey("France")){ // check key before removing it
    countries.Remove("France");
}
countries.Clear();

C# 中的哈希表

Dictionary 不同,Hashtable 是一个非泛型集合。它还存储键值对。

通过计算每个键的哈希码并将其存储在单独的内部存储桶中,它通过在访问值时匹配所提供键的哈希码来改进查找。看一下 Hashtable 的一些特征。

C# 中 Hashtable 的特征

  1. 键值对保存在 Hashtables 中。
  2. 它属于命名空间 SystemCollection
  3. 实现了 IDictionary 接口。
  4. 键不能为空,并且必须是不同的。
  5. 值可能重复或为空。
  6. 可以通过向索引器提供相关键来获取值,如 Hashtable[key]
  7. DictionaryEntry 对象用于存储元素。

C# 中创建一个哈希表

查看以下不言自明的代码以了解 Hashtable 的创建。

`Hashtable` rollno_names = new `Hashtable`();
rollno_names.Add(1,"Ali"); //adding a key/value using the Add() method
rollno_names.Add(2,"Haider");
rollno_names.Add(3,"Saad");
//The following throws runtime exception: key already added.
//rollno_names.Add(3, "Rafay");
foreach(DictionaryEntry i in rollno_names)
    Console.WriteLine("Key: {0}, Value: {1}", i.Key, i.Value);
//creating a `Hashtable` using collection-initializer syntax
var countries= new `Hashtable`(){
    {"UK", "UnitedKingdom"},
    {"USA", "United State of America"},
    {"PK", "Pakistan"}
};
foreach(DictionaryEntry j in countries)
    Console.WriteLine("Key: {0}, Value: {1}", j.Key, j.Value);

我们可以像 Dictionary 一样创建 Hashtable。唯一的区别是它是非泛型的,因此我们不必指定键的数据类型及其对应的值。

C# 的哈希表中添加字典

我们可以创建 Dictionary 的对象,并且通过在创建 Hashtable 时简单地传递该对象,我们可以在 Hashtable 中添加 Dictionary 键值对。

更新 C# 中的哈希表

通过在索引器中输入键,你可以从 Hashtable 检索现有键的值。由于 Hashtable 是一个非泛型集合(意味着键和值都没有数据类型),因此在从中获取值时需要将其类型转换为字符串。

看看下面的代码。

//creating a Hashtable using collection-initializer syntax
var countries= new Hashtable(){
    {{"UK", "UnitedKingdom"},
    {"USA", "United State of America"},
    {"PK", "Pakistan"}
};
string countrynameUK = (string) countries["UK"]; //cast to string
string countrynameUSA = (string) countries["USA"]; //cast to string
Console.WriteLine(countrynameUK);
Console.WriteLine(countrynameUSA);
countries["UK"] = "Euorpe"; // update value of UK key
countries["USA"] = "America"; // update value of USA key
if(!countries.ContainsKey("France")){
    countries["France"] = "Western Euorpe";
}

C# 中的哈希表中删除元素

Hashtable 的给定键值对使用 Remove() 方法删除。如果提供的键不存在于 Hashtable 中,则抛出 KeyNotfoundException 异常;因此,在删除密钥之前,请使用 ContainsKey() 方法查看它是否已经存在。

使用 Clear() 函数一次删除每个项目。

var countries= new Hashtable(){
    {"UK", "UnitedKingdom"},
    {"USA", "United State of America"},
    {"PK", "Pakistan"}
};
countries.Remove("UK"); // removes UK
//countries.Remove("France"); //throws run-time exception: KeyNotFoundException
if(countries.ContainsKey("France")){ // check key before removing it
    countries.Remove("France");
}
countries.Clear(); //removes all elements

C# 中的字典与哈希表

Dictionary Hashtable
如果我们试图发现一个不存在的键,它要么返回要么抛出异常。 如果我们试图发现一个不存在的键,它会返回 null。
因为没有装箱和拆箱,它比 Hashtable 快。 由于需要装箱和拆箱,它需要比字典更长的时间。
线程安全仅适用于公共静态成员。 Hashtable 的成员都是线程安全的,
由于 Dictionary 是泛型类型,任何数据类型都可以与它一起使用(创建它时,我们必须指定键和值的数据类型)。 不是泛型类型。
具有强类型键和值的 Hashtable 实现称为 Dictionary 由于 Hashtables 是灵活类型的数据结构,因此可以添加任何键和值类型。

基于这些事实,我们可以说 Dictionary 优于 Hashtable。因为你可以将任何随机项插入 Dictionary<TKey, TValue> 并且你不必强制转换取出的值,所以你可以获得类型安全。