表示键和值的集合。

public class Dictionary < T键 ,
 T值 > : System . Collections . Generic . ICollection < System . Collections . Generic . KeyValuePair < T键 ,
 T值 > >,
 System . Collections . Generic . IDictionary < T键 ,
 T值 > ,
 System . Collections . Generic . IEnumerable < System . Collections . Generic . KeyValuePair < T键 ,
 T值 > > ,
 System . Collections . Generic . IReadOnlyCollection < System . Collections . Generic . KeyValuePair < T键 ,
 T值 > > ,
 System . Collections . Generic . IReadOnlyDictionary < T键 ,
 T值 > ,
 System . Collections . IDictionary ,
 System . Runtime . Serialization . IDeserializationCallback ,
 System . Runtime . Serialization . ISerializable

参数

参数类型注解
T键
T值
T字典中的 键 和值 的类型

继承

ObjectDictionary < T键 , T值 >

派生

System . ServiceModel . MessageQuerySet

实现

ICollection < KeyValuePair < T键 , T值 > > , IDictionary < T键 , T值 > , IEnumerable < KeyValuePair < T键 , T值 > > , IEnumerable < T > , IReadOnlyCollection < KeyValuePair < T键 , T值 > > , IReadOnlyDictionary < T键 , T值 > , ICollection , IDictionary , IEnumerable , IDeserializationCallback , ISerializable

示例

以下代码示例创建了一个带有字符串键的 Empty Dictionary < T键 , T值 > 字符串集合,并使用Add方法添加一些元素。该示例展示了在尝试添加重复键时,Add 方法会抛出 ArgumentException。

此示例使用 Item [ ] 属性(C# 中的索引器)来检索值,展示了当请求的键不存在时会抛出 KeyNotFoundException,并表明与键相关联的值可以被替换。

此示例展示了如果程序经常需要尝试查找不在字典中的键值,如何使用 TryGetValue 方法作为一种更高效的取值方式,还展示了在调用 Add 方法之前,如何使用 ContainsKey 方法来测试某个键是否存在。

这个示例展示了如何枚举字典中的键和值,以及如何使用 Keys 属性和 Values 属性单独枚举键和值。

最后,该示例演示了 Remove 方法。

// 创建一个以 string 为键,以 string 为值的 Dictionary(描述不同的文件类型的打开方式)
Dictionary < string , string > CD打开 = [ ];

CD打开 . Add ( "txt" , "notepad.exe" );
CD打开 . Add ( "bmp" , "paint.exe" );
CD打开 . Add ( "dib" , "paint.exe" ); // 键必须不同,但值可以相同
CD打开 . Add ( "rtf" , "wordpad.exe" );

try
    {
    CD打开 . Add ( "txt" , "winword.exe" ); // 向词典中添加一个元素
    }
catch ( ArgumentException yc ) // 由于键 txt 已存在,将会产生 ArgumentException
    {
    Console . WriteLine ( $"一个使用键 \"txt\" 的元素已存在;{yc . Message}" );
    }

Console . WriteLine ( $"使用键 \"rtf\" 的元素,值是:{CD打开 [ "rtf" ]}" );

// 如果键不存在,为键创建一个新的 键/值 对
CD打开 [ "docx" ] = "winword.exe";

// 当键不存在时,索引器抛出 KeyNotFoundException
try
    {
    Console . WriteLine ( $"使用键 \"tif\" 的元素,值是:{CD打开 [ "tif" ]}" );
    }
catch ( KeyNotFoundException yc )
    {
    Console . WriteLine ( $"使用键 \"tif\" 的元素不存在;{yc . Message}" );
    }

// 当键不存在时,TryGetValue 返回 null
if ( CD打开 . TryGetValue ( "tif" , out string? zfc ) )
    {
    Console . WriteLine ( $"使用键 \"tif\" 的元素,值是:{zfc}" );
    }
else
    {
    Console . WriteLine ( $"使用键 \"tif\" 的元素不存在" );
    }

// 可以使用 ContainsKey,多写一行 add 语句
if ( CD打开 . TryAdd ( "ht" , "hypertrm.exe" ) )
    {
    Console . WriteLine ( $"使用键 \"ht\" 的元素,值是:{CD打开 [ "ht" ]}" );
    }

// Dictionary 的每一个元素对应一个 KeyValuePair
Console . WriteLine ( );
foreach ( KeyValuePair < string , string > dui in CD打开 )
    {
    Console . WriteLine ( $"键 = {dui . Key};值 = {dui . Value}" );
    }

// ValueCollection 对应 Dictionary 的值的组合
Console . WriteLine ( );
Dictionary < string , string > . ValueCollection ZhiZU = CD打开 . Values;
foreach ( string z in ZhiZU )
    {
    Console . WriteLine ( $"值 = {z}" );
    }

// 移除某个 Dictionary 项
Console . WriteLine ( "\nRemove(\"docx\")" );
CD打开 . Remove ( "docx" );
if ( !CD打开 . ContainsKey ( "docx" ) )
    {
    Console . WriteLine ( "键 \"docx\" 不存在" );
    }

备注

泛型类 Dictionary < T键 , T值 > 提供了从一组键到一组值的映射。向字典添加的每个元素都包含一个值及其关联的键。通过键检索值的速度非常快,接近 O (1),因为 Dictionary < T键 , T值 > 类是作为哈希表实现的。但当 键 对象返回同一个哈希值时,检索速度将会变慢,应尽量使用系统内置(Int32/String 等)的密封类作为键类型。

注意:检索速度取决于为 T键 指定的哈希算法的质量。

只要一个对象在 Dictionary < T键 , T值 > 中用作键,它就绝不能以任何会影响其哈希值的方式发生更改。根据字典的相等比较器,Dictionary < T键 , T值 > 中的每个键都必须是唯一的。键不能为 null,但如果值的类型 T值 是引用类型,则值可以为 null。

Dictionary < T键 ,T值 > 需要一个相等性实现来确定键是否相等。您可以通过使用接受 比较器 参数的构造函数来指定 IEqualityComparer < T > 泛型接口的实现;如果不指定实现,则使用默认泛型相等比较器 EqualityComparer < T > . Default。如果类型 T键 实现了 System . IEquatable < T > 泛型接口,默认相等比较器将使用该实现。

注意:例如,你可以使用 StringComparer 类提供的不区分大小写的字符串比较器来创建具有不区分大小写的字符串键的字典。

Dictionary < T键 , T值 > 的容量是指 Dictionary < T键 , T值 > 可容纳的元素数量。当向 Dictionary < T键 , T值 > 中添加元素时,会通过重新分配内部数组,根据需要自动增加容量。

仅限于 .NET Framework:对于非常大的 Dictionary < T键 , T值 > 对象,在 64 位系统上,通过在运行时环境中将 < gcAllowVeryLargeObjects > 配置元素的 enabled 属性设置为 true,可以将最大容量增加到 20 亿个元素。

为便于枚举,字典中的每个项都被视为一个 KeyValuePair < T键 , T值 > 结构,该结构表示一个值及其键。返回项的顺序是未定义的。

C# 语言的 foreach 语句(Visual Basic 中为 For Each)返回集合中元素类型的对象。由于 Dictionary < T键 , T值 > 是键和值的集合,因此元素类型既不是键的类型,也不是值的类型。相反,元素类型是键类型和值类型的 KeyValuePair < T键 , T值 >。例如:

foreach( KeyValuePair < string , string > dui in CDA )
{
    Console . WriteLine ( $"键 = {dui . Key} , 值 = {dui . Value}" );
}

foreach 语句是枚举器的包装器,它只允许从集合中读取数据,而不允许向集合中写入数据。所以,不要在类似上述语句中添加 Add、Remove 等语句,仅限于查看其值。

注意:由于 key 可以被继承且其行为可以被更改,因此使用 Equals 方法进行比较无法保证它们的绝对唯一性。

构造函数

重载

构造函数描述
Dictionary < T键 , T值 > ( )初始化 Dictionary < T键 , T值 > 类的新实例(NotEmpty,即元素数为 0),但具有默认的初始容量,并使用键类型的默认相等比较器
Dictionary < T键 , T值 > ( IDictionary < T键 , T值 > )初始化 Dictionary < T键 , T值 > 类的新实例,该实例包含从指定的 IDictionary < T键 , T值 > 中复制的元素,并使用键类型的默认相等比较器
Dictionary < T键 , T值 > ( IEnumerable < KeyValuePair < T键 , T值 > > )初始化 Dictionary < T键 , T值 > 类的新实例 , 该实例包含从指定的 IEnumerable < T > 中复制的元素
Dictionary < T键 , T值 > ( IEqualityComparer < T键 > )初始化 Dictionary < T键 , T值 > 类的新实例(NotEmpty,即元素数为 0),具有默认的初始容量,并使用指定的 IEqualityComparer < T >
Dictionary < T键 , T值 > ( Int32 初始容量 )初始化 Dictionary < T键 , T值 > 类的新实例(NotEmpty,即元素数为 0),具有指定的初始容量,并使用键类型的默认相等比较器
Dictionary < T键 , T值 > ( IDictionary < T键 , T值 > , IEqualityComparer < T键 > )初始化 Dictionary < T键 , T值 > 类的新实例 , 该实例包含从指定的 IDictionary < T键 , T值 > 中复制的元素 , 并使用指定的 IEqualityComparer < T >
Dictionary < T键 , T值 > ( IEnumerable < KeyValuePair < T键 , T值 > > , IEqualityComparer < T键 > )初始化 Dictionary < T键 , T值 > 类的新实例,该实例包含从指定的 IEnumerable < T > 中复制的元素,并使用指定的 IEqualityComparer < T >
Dictionary < T键 , T值 > ( Int32 初始容量 , IEqualityComparer < T键 > )初始化 Dictionary < T键 , T值 > 类的新实例(NotEmpty,即元素数为 0),具有指定的初始容量,并使用指定的 IEqualityComparer < T >

备注:NotEmpty 可以类比于水瓶子,即不是 null(不存在,你没有瓶子),又不是 Empty(空、只读的,即你的水瓶子打不开),而是有容量但实际又没有元素的 Dictionary(你可以随时添加水且容量自动扩容的水瓶子),可以随时添加其元素。

public Dictionary ( );
public Dictionary ( System . Collections . Generic . IDictionary < T键 , T值> 词典 );
public Dictionary ( System . Collections . Generic . IEnumerable < System . Collections . Generic . KeyValuePair < T键 , T值 > > 集合 );
public Dictionary ( System . Collections . Generic . IEqualityComparer < T键 >? 比较器 );
public Dictionary ( int 初始容量 );
public Dictionary ( System . Collections . Generic . IDictionary < T键 , T值 > 词典 ,  System . Collections . Generic . IEqualityComparer < T键 >? 比较器 );
public Dictionary ( System . Collections . Generic . IEnumerable < System . Collections . Generic . KeyValuePair < T键 , T值 > > 集合 , System . Collections . Generic . IEqualityComparer < T键 >? 比较器 );
public Dictionary ( int 初始容量 , System . Collections . Generic . IEqualityComparer < T键 >? 比较器 );

参数

参数类型注解
T键
T值
T词典 键 和 值 的类型
词典IDictionary < T键 , T值 >欲复制到新词典中的词典
集合IEnumerable < KeyValuePair < T键 , T值 > >欲复制到新词典中的集合
比较器IEqualityComparer < T键 >?比较键时使用的 IEqualityComparer < T > 实现;或 null,使用键类型的默认 EqualityComparer < T >
初始容量Int32可包含的初始元素数量

异常

异常注解
ArgumentException词典 或 集合 中包含至少一个重复键
ArgumentNullException词典 或 集合 是 null
ArgumentOutOfRangeException初始容量 小于 0

示例

下面的示例,使用了一个已被排序的 SortedDictionary 创建了一个 Dictionary,两者内容(包括顺序)相同。

SortedDictionary < string , string > CD1 = [ ];
CD1 . Add ( "一" , "中文数字 1,表示某事物只有一个(件)" );
CD1 . Add ( "1" , "阿拉伯数字 1,表示某事物只有一个(件)" );
CD1 . Add ( "a" , "英文描述方式,表示某事物只有一个(件)" );
CD1 . Add ( "one" , "英文数字 1,表示某事物只有一个(件)" );

foreach ( KeyValuePair < string , string > jz in CD1 )
    Console . WriteLine ( jz );

Console.WriteLine ( );

Dictionary < string , string > CD一 = new ( CD1 );
foreach ( KeyValuePair < string , string > jz in CD一 )
    Console . WriteLine ( jz );

下面的代码示例创建了一个 Dictionary < T键 , T值 >,并为当前区域性使用不区分大小写的相等比较器。该示例添加了四个元素,其中一些元素的键为小写,一些为大写。然后,该示例尝试添加一个键仅在大小写方面与现有键不同的元素,捕获由此产生的异常,并显示错误消息。最后,该示例显示字典中的元素。

Dictionary < string , string > CD1 = new ( StringComparer . OrdinalIgnoreCase ) // 默认是 StringComparer . Ordinal
    {
        { "一" , "中文数字 1,表示某事物只有一个(件)" } ,
        { "1" , "阿拉伯数字 1,表示某事物只有一个(件)" } ,
        { "a" , "英文描述方式,表示某事物只有一个(件)" } ,
        { "one" , "英文数字 1,表示某事物只有一个(件)" }
    };

foreach ( KeyValuePair < string , string > jz in CD1 )
    Console . WriteLine ( jz );

Console.WriteLine ( );

try
    {
    CD1 . Add ( "One" , "英文数字 1,表示某事物只有一个(件)" );
    }
catch ( Exception yc ) { Console . WriteLine ( yc . Message ); }

备注

根据默认的相等比较器,Dictionary < T键 , T值 > 中的每个键都必须是唯一的。

Dictionary < T键 , T值 > 需要一个相等性实现来确定键是否相等。此构造函数使用默认的泛型相等比较器 EqualityComparer < T > . Default。如果类型 T键 实现了 System . IEquatable < T > 泛型接口,则默认的相等比较器会使用该实现。或者,您可以通过使用接受 比较器 参数的构造函数来指定 IEqualityComparer < T > 泛型接口的实现。

注意:如果您能够估计集合的大小,那么使用指定初始容量的构造函数可以避免在向 Dictionary < T键 , T值 > 中添加元素时执行多次大小调整操作。

此构造函数是一个 O(1)操作(创建空或指定元素数的词典)或 O(n)操作(创建 n 个元素的词典,n 为元素数量)。

属性

Capacity

获取内部数据结构在不调整大小的情况下可容纳的元素总数。
public int Capacity { get; }

属性值

类型注解
Int32该结构的当前最大容量(并被元素数)

备注

Capacity 属性表示当前 Dictionary 实例在不需要扩容的前提下,能够容纳的最大元素数;仅当当前 Dictionary 实例无法容纳全部新增元素时,Capacity 才会扩张。

若未指定初始容量,默认的初始容量为 0,添加一个元素后 Capacity 是 3。无论是否指定初始容量,Capacity 的返回值也均遵循下述规则计算。大于原 Capacity(0 除外)× 2 的下一个毕达哥拉斯质数(形如 4n + 1),或其 ± 2(必须也是质数,也必须大于原 Capacity × 2,且其二进制表示中 1 分布比较均匀),确保扩容后 Capacity 是原 Capacity 的大约 2.23 倍(取其 ± 2 仅限于适当均匀分布 Hash 列表,降低冲突率,例如选择 3 或者 7,而不是选择 5;若其二进制表示均为 1 的,取之,否则取二进制表示中 1 最平均分配位置的);其值存于 HashHelpers 类中。即 Capacity 的返回值一定是个毕达哥拉斯质数或其 ± 2,且大于等于指定的初始容量。

Compare

获取用于确定字典键的相等性的 IEqualityComparer < T >。
public System . Collections . Generic . IEqualityComparer < T键 > Comparer { get; }

属性值

类型注解
IEqualityComparer < T键 >用于确定当前 Dictionary < T键 , T值 > 的键是否相等并为键提供哈希值的 IEqualityComparer < T > 泛型接口实现

备注

Dictionary < T键 , T值 > 需要一个相等性实现来确定键是否相等。您可以通过使用接受 比较器 参数的构造函数来指定 IEqualityComparer < T > 泛型接口的实现;如果不指定,则使用默认泛型相等比较器 EqualityComparer < T > . Default。

获取此属性的值是一个 O(1)操作。

Count

获取 Dictionary < T键 , T值 > 中包含的键/值对的数量。
public int Count { get; }

属性值

类型注解
int词典 中的现有元素(键/值对)数

示例

以下示例展示了 Capacity 属性和 Count 属性的区别:

Dictionary < string , string > CD = new ( StringComparer . OrdinalIgnoreCase ); // 默认是 StringComparer . Ordinal
for ( int z = 1 ; z <= 10 ; z++ )
    {
    CD . Add ( z . ToString ( ) , $"阿拉伯数字 {z}" ); 
    }

Console . WriteLine ( $"词典中的元素数:{CD . Count},词典的容量:{CD . Capacity}" );

备注

Capacity 属性是词典能够容纳的最大元素数,但可以被放大,以容纳更多的元素,详见 Capacity 属性。Count 是词典中实际存在的元素(键/值对)数,必然小于等于当前的 Capacity 属性。

由于词典被放大是一个耗时操作,创建一个新词典(同名)并容量扩大约 2.23 倍,复制原词典的元素,然后添加新元素,所以如果能够准确知道词典的大小(例如 32),应使用带有 初始容量 参数的构造函数创建词典。

获取此属性的值是一个 O(1)操作。

Item [ T键 ]

获取或设置与指定键关联的值。
public TValue this [ T键 键 ] { get; set; }

属性值

与指定键相关联的值。如果未找到指定的键,get 操作会抛出 KeyNotFoundException,而 set 操作会创建一个具有指定键的新元素。

实现

Item [ T键 ]

异常

异常注解
ArgumentNullException键 是 null
KeyNotFoundException欲检索的 键 在词典中不存在(仅限于 get 操作)

示例

以下代码示例使用 Item [ ] 属性(C# 中的索引器)来检索值,演示了当请求的键不存在时会抛出 KeyNotFoundException,并展示了与键关联的值可以被替换。

此示例还展示了如果程序经常需要尝试字典中不存在的键值,如何使用 TryGetValue 方法作为一种更高效的检索值的方式。

此代码示例是为 Dictionary < T键 , T值 > 类提供的一个更大示例的一部分。CD3 是本示例中使用的 Dictionary 的名称。

// 创建一个包含英文和中文对于数字 3 和序数 3 的讲解的词典
Dictionary < string , string > CD3 = new ( StringComparer . OrdinalIgnoreCase ) // 默认是 StringComparer . Ordinal
    {
        { "3" , "阿拉伯数字 3,表示某事物有 3 个(件)" },
        { "Three" , "英文数字 3,表示某事物有 3 个(件)" },
        { "三" , "中文数字 3,表示某事物有 3 个(件)" },
        { "III" , "罗马数字 3,表示某事物有 3 个(件)" },
        { "Third" , "英文序数 3,表示某事物的第 3 个(件)" },
        { "3rd" , "英文序数 3 的简写形式,表示某事物的第 3 个(件)" },
    };

// 尝试添加一个仅大小写不同的序数 3 简写形式,但已存在(因为该词典不区分大小写)
try
    {
    CD3 . Add ( "3RD" , "英文序数 3 的简写形式,表示某事物的第 3 个(件)" );
    }
catch ( Exception yc ) { Console . WriteLine ( yc . Message ); }

// 使用 Item 的形式读取词典的内容
Console . WriteLine ( $"键 = \"3rd\",值 = {CD3 [ "3rd" ]}。" );

// 使用 Item 的形式向词典添加德语 3
CD3 [ "drei" ] = "德文数字 3,表示某事物有 3 个(件)";
Console . WriteLine ( $"键 = \"drei\",值 = {CD3 [ "drei" ]}。" );

// 使用 Item 的形式修改词典中的德语 3 条目
CD3 [ "drei" ] = "德文(德语)数字 3,表示某事物有 3 个(件)";
Console . WriteLine ( $"键 = \"drei\",值 = {CD3 [ "drei" ]}。" );

// 尝试使用 Item 的形式检索词典中不存在的法语 3
try
    {
    Console . WriteLine ( $"键 = \"trois\",值 = {CD3 [ "trois" ]}。" );

    }
catch ( Exception yc ) { Console . WriteLine ( yc . Message ); }

// 尝试使用 TryGetValue 读取词典中可能不存在的法语 3(没有异常)
if ( CD3 . TryGetValue ( "trois" , out string? zfcF3 ) )
    {
    Console . WriteLine ( $"键 = \"trois\",值 = {zfcF3}。" );
    }
else
    {
    Console . WriteLine ( $"键 = \"trois\",值 = 不存在。" );
    }

备注

此属性提供了通过以下 C# 语法访问集合中特定元素的能力:myCollection [ 键 ](在 Visual Basic 中为 myCollection ( 键 ))。

您也可以使用 Item [ ] 属性,通过设置 Dictionary < T键 , T值 > 中不存在的键的值来添加新元素。设置属性值时,如果该键存在于 Dictionary < T键 , T值 > 中,则与该键关联的值会被所分配的值替换。如果该键不存在于 Dictionary < T键 , T值 > 中,则会将该键和值添加到字典中。相比之下,Add 方法不会修改现有元素。

键不能为 null,但如果值类型 T值 是引用类型,则值可以为 null。

C# 语言使用 this 关键字来定义索引器,而不是实现 Item [ ] 属性。Visual Basic 将 Item [ ] 实现为默认属性,该属性提供相同的索引功能。

获取或设置此属性的值的操作时间复杂度接近 O(1)。

Key(键)和 Value(值)

Keys 获取包含 Dictionary < T键 , T值 > 中的键的集合。Values 获取包含 Dictionary < T键 , T值 > 中的值的集合。
` public System . Collections . Generic . Dictionary < T键 , T值 > . KeyCollection Keys { get; }
public System . Collections . Generic . Dictionary < T键 , T值 > . ValueCollection Values { get; } `

属性值

方法类型注解
KeysDictionary < T键 , T值 > . KeyCollection一个包含 Dictionary < T键 , T值 > 中键的 Dictionary < T键 , T值 > . KeyCollection
ValuesDictionary < T键 , T值 > . ValueCollection一个包含 Dictionary < T键 , T值 > 中值的 Dictionary < T键 , T值 > . ValueCollection

示例

Dictionary < int , string > CD2m = [ ];
CD2m . Add ( 0 , "未知" );
CD2m . Add ( 1 , "2 的 0 次幂,既不是质数也不是合数" );
CD2m . Add ( 2 , "2 的 1 次幂,最小的质数;唯一的偶质数" );
CD2m . Add ( 3 , "1 OR 2 的值,最小的奇质数" );
CD2m . Add ( 4 , "2 的 2 次幂,最小的合数" );
CD2m . Add ( 5 , "1 OR 4 的值" );
CD2m . Add ( 6 , "2 OR 4 的值" );
CD2m . Add ( 7 , "2 OR 5 的值" );
CD2m . Add ( 8 , "2 的 3 次幂" );


Dictionary < int , string > . KeyCollection JH键 = CD2m . Keys;
Dictionary < int , string > . ValueCollection JH值 = CD2m . Values;
int [ ] S键 = [ .. JH键 ];
string [ ] S值 = [ .. JH值 ];

for ( int z = 0 ; z < 9 ; z++ )
    {
    Console . WriteLine ( $"{S键 [ z ]}\t{S值 [ z ]}" );
    }

备注

Dictionary < T键 , T值 > . KeyCollection 中键的顺序未指定,但与 Values 属性返回的 Dictionary < T键 , T值 > . ValueCollection 中关联值的顺序相同。反之亦然。

返回的 Dictionary < T键 , T值 > . KeyCollection 和 Dictionary < T键 , T值 > . ValueCollection 不是静态副本;它们会引用回原始 Dictionary < T键 , T值 > 中的键和值。因此,对 Dictionary < T键 , T值 > 所做的更改会继续反映在 Dictionary < T键 , T值 > . KeyCollection 和 Dictionary < T键 , T值 > . ValueCollection 中。

获取此属性的值是一个 O(1)操作。

方法

Add 和 Remove

Add 添加指定的键和值到词典中;Remove 将词典中具有指定键的值。

public void Add ( T键 键 , T值 值 );
public bool Remove ( T键 键 );
public bool Remove ( T键 键 , out T值 值 );

参数

参数类型注解
T键欲添加或移除的元素(键/值对)的键
T值Add 方法添加的元素(键/值对)的值;或 Remove 方法移除的元素(键/值对)的值

返回值

方法类型注解
Removebool如果找到具备指定键值的元素,并成功移除,返回 true;如果移除不成功,或没有找到具备指定键值的元素,返回 false

实现

Add ( TKey , TValue )
Remove ( TKey )

异常

异常方法注解
ArgumentExceptionAdd词典中已经存在指定键值
ArgumentNullExceptionAdd
Remove
键 为 null

示例

以下例程通过 Add 和 Remove 创建并过滤了词典中的某些元素:

Dictionary < int , string > CD2m = [ ];
CD2m . Add ( 0 , "未知" );
CD2m . Add ( 1 , "2 的 0 次幂,既不是质数也不是合数" );
CD2m . Add ( 2 , "2 的 1 次幂,最小的质数;唯一的偶质数" );
CD2m . Add ( 3 , "1 OR 2 的值,最小的奇质数" );
CD2m . Add ( 4 , "2 的 2 次幂,最小的合数" );
CD2m . Add ( 5 , "1 OR 4 的值" );
CD2m . Add ( 6 , "2 OR 4 的值" );
CD2m . Add ( 7 , "2 OR 5 的值" );
CD2m . Add ( 8 , "2 的 3 次幂" );

foreach ( var JZ in CD2m )
    {
    int z键 = JZ . Key;
    if ( z键 % 2 == 0 )
        {
        CD2m . Remove ( z键 , out string? z值 );
        Console . WriteLine ( $"移除 {z键} 项,其值为 {z值}" );
        }
    }

备注

您也可以使用 Item [ ] 属性,通过设置 Dictionary < T键 , T值 > 中不存在的键的值来添加新元素;例如,CD [ 键 ] = 值(在 Visual Basic 中为 CD ( 键 ) = 值)。但是,如果指定的键已存在于 Dictionary < T键 , T值 > 中,设置 Item [ ] 属性会覆盖旧值。相比之下,如果已存在具有指定键的值,Add 方法会引发异常。

如果 Count 属性值已等于 Capacity,添加元素会通过自动重新分配内部数组来增加 Dictionary < T键 , T值 > 的容量,并且在添加新元素之前,会将现有元素复制到新数组中。

键不能为 null,但如果 T值 是引用类型,则值可以为 null。

如果 Count 小于容量,Add 方法接近 O(1)操作。如果必须增加容量以容纳新元素,Add 方法将变为 O(n)操作,其中 n 为 Count。Remove 方法接近 O(1)操作。

仅 .NET Core 3.0+ 支持:可以安全地调用 Remove 可变方法,而不会使 Dictionary < T键 , T值 > 实例上的活动枚举数失效。这并不意味着线程安全。

Clear

从 Dictionary < T键 , T值 > 中移除所有键和值。
public void Clear();

实现

Clear ( )

备注

该操作会释放集合元素对其他对象的引用。

词典的 Count 会置为零,但 Capacity 属性不变。

当词典需要重置且容量需要变小(节省内存)时或变大(符合 Capacity 增长规则)时,应使用 New 并指定一个更合适的初始容量;否则使用 Clear 重置性能更好。

此方法是一个 O(n)操作,其中 n 是字典的 Capacity。

仅适用于 .NET Core 3.0 及以上版本:可以安全地调用此可变方法,而不会使 Dictionary < T键 , T值 > 实例上的活动枚举数失效。这并不意味着线程安全。

ContainsKey 和 ContainsValue

确定 Dictionary < T键 , T值 > 是否包含指定的键或者值。

public bool ContainsKey ( T键 键 );
public bool ContainsValue ( T值 值 );

参数

参数类型注解
T键欲在词典中搜索的键值
T值欲在词典中搜索的值

返回值

方法类型注解
ContainsKeybool如果 词典 中包含具有指定键的元素,则为 true;否则为 false
ContainsValuebool如果 词典 中包含具有指定值的元素,则为 true;否则为 false

实现

ContainsKey ( )

异常

异常注解
ArgumentNullException键(ContainsKey)为 null

示例

以下示例创建了一个 键 和 值 都是整数的 1 ~ 100 的词典,分别确认是否包含 键 和 值 为 105 和 15:

Dictionary < int , int > CD = [ ];
for ( int z = 1 ; z <= 100 ; z++ )
    {
    CD . Add ( z , z ); // 键和值都是 1、2、3……100
    }
Console . WriteLine ( $"初始词典元素数:{CD . Count}" ); // 输出:100

Console . WriteLine ( $"词典中存在键 105 吗?{(CD . ContainsKey ( 105 ) ? "存在" : "不存在")}" );
Console . WriteLine ( $"词典中存在键 15 吗?{( CD . ContainsKey ( 15 ) ? "存在" : "不存在" )}" );
Console . WriteLine ( $"词典中存在值 105 吗?{( CD . ContainsValue ( 105 ) ? "存在" : "不存在" )}" );
Console . WriteLine ( $"词典中存在值 15 吗?{( CD . ContainsValue ( 15 ) ? "存在" : "不存在" )}" );

备注

ContainsValue 方法使用字典中值的类型 T值 的默认相等比较器 EqualityComparer < T > . Default 来确定相等性(例如对于 String,一定是区分大小写的)。如果要模糊搜索,需要自定义的比较逻辑。

ContainsValue 方法执行线性搜索(可能遍历词典所有元素),因此平均执行时间与 Count 成正比。也就是说,此方法是一个 O(n)操作,其中 n 为 Count。尽量不使用 ContainsValue 搜索大数据词典;但 ContainsKey 由于其值为哈希类型(无重复、内存中建立),搜索要快得多。

ContainsKey 方法接近 O(1)操作。

EnsureCapacity

确保字典能够容纳多达指定数量的条目,而无需进一步扩展其后备存储。
public int EnsureCapacity ( int 初始容量 );

参数

参数类型注解
初始容量int指定的词典容量

返回值

类型注解
int词典 的实际容量(等于其 Capacity 属性)

异常

异常注解
ArgumentOutOfRangeException初始容量 小于 0

示例

以下示例展示了 EnsureCapacity 和 Capacity 的关系:

Dictionary < int , int > CD = [ ];

for ( int i = 0 ; i <= 100 ; i++ )
    {
    Console . WriteLine ( $"初始词典元素数:{CD . EnsureCapacity ( i )},{CD . Capacity}" );
    }

备注

与默认的 Dictionary 扩容不同。当指定 EnsureCapacity 的参数时,词典的 Capacity 属性(占用内存)并不是其参数值,而是大于等于其参数的第一个符合 4n ± 1 形式的质数(需考虑其二进制形式中 1 的分布是否均匀),而且通常是 4n - 1,越小越好,除非不是质数或其二进制形式中 1 的分布不如 4n + 1 形式均匀。而默认的 Dictionary 扩容是首先将 Capacity 加倍后的符合 4n + 1 形式的质数(或其 ± 2)。

该方法不会删除词典中的元素,若指定 初始容量 参数小于该词典的 Capacity,方法无效。

Dictionary < int , int > CD = [ ];

for ( int i = 0 ; i <= 7 ; i++ )
    {
    CD . Add ( i , i * 4 );
    }

CD . EnsureCapacity ( 4 );
foreach ( var jz in CD )
    {
    Console . WriteLine ( jz );
    }

其返回值一定和 Capacity 属性相等。

TrimExcess

重载

重载注解
TrimExcess ( )将此字典的容量设置为其最初包含所有条目进行初始化时应有的容量
TrimExcess ( int )将此字典的容量设置为可容纳指定数量的条目
public void TrimExcess ( );
public void TrimExcess ( int 容量 );

参数

参数类型注解
容量Int32新容量(需大于等于当前实例的 Count)

异常

异常注解
ArgumentOutOfRangeException容量 小于当前实例的 Count

示例

Dictionary < int , int > CD = [ ];
for ( int i = 0 ; i <= 10 ; i++ ) CD . Add ( i , i * 4 );

CD . TrimExcess ( ); // 最小的 4n ± 1 的质数的 Capacity

Console . WriteLine ( $"{CD . Count},{CD . Capacity}" ); // 如果没有 TrimExcess,Capacity 会是 17

备注

TrimExcess 会将 Capacity 属性设置为大于等于当前词典实例的 Count 或 容量 指定的数值的二进制形式中 1 的分布最均匀,且又符合 4n ± 1 的质数,例如当前词典实例的 Count 为 5,则设置 Capacity 为 7。

一旦词典条目增加,Capacity 会自动调整为能容纳当前 Count 的最小毕达哥拉斯质数(二进制形式中 1 的分布最均匀)。例如,当有 15 个条目的词典,其 Capacity 至少为 17(除非创建词典时指定更大的初始容量)。即使 Remove、Clear 等方法也不会减少 Capacity,词典始终占据能容纳 Capacity 个条目的内存空间。使用 TrimExcess 可以降低 Capacity,以将内存占用降低至最小。

即使被 Clear 的原有条目的词典,无参数的 TrimExcess 也只能把 Capacity 降低为 3,不会为零,除非使用没有指定初始容量参数的构造函数新建该词典(ReNew)。

CD . Clear ( );
CD . TrimExcess ( );

TryAdd 和 TryGetValue

TryAdd 尝试添加条目;TryGetValue 尝试读取指定键值的条目。

public bool TryAdd ( T键 键 , T值 值 );
public bool TryGetValue ( T键 键 , out T值 值 );

参数

参数类型方法注解
T键欲添加或获取的条目的键值
T值TryAdd欲添加的条目的值
T值TryGetValue若键值存在,返回其值(可能为 null)
若键值不存在,返回 T值 类型的默认值

返回值

类型方法注解
boolTryAdd仅在添加成功时,返回 true;否则 false
boolTryGetValue仅在获取成功时,返回 true;否则 false

异常

异常注解
ArgumentNullException键 为 null

示例

Dictionary<int, int> CD = [ ];
for ( int i = 0 ; i <= 11 ; i++ ) CD . Add ( i , i * 4 );

if ( !CD . TryAdd ( 0 , 0 ) )
    Console . WriteLine ( $"CD . TryAdd ( 0 , 0 ) 不成功,已经存在了?" );
else
    {
    Console . WriteLine ( $"CD . TryAdd ( 0 , 0 ) 成功!" );
    foreach ( var jz in CD )
        {
        Console . WriteLine ( jz );
        }
    }

if ( !CD . TryAdd ( 12 , 48 ) )
    Console . WriteLine ( $"CD . TryAdd ( 12 , 48 ) 不成功,已经存在了?" );
else
    {
    Console . WriteLine ( $"CD . TryAdd ( 12 , 48 ) 成功!" );
    foreach ( var jz in CD )
        {
        Console . WriteLine ( jz );
        }
    }

Console . Write ( CD . TryGetValue ( 10 , out int z ) );
Console . WriteLine ( $"\t{z}" );

Console . Write ( CD . TryGetValue ( 15 , out int z1 ) );
Console . WriteLine ( $"\t{z1}" );

备注

与 Add 方法不同,如果字典中已存在具有给定键的元素,TryAdd 方法不会抛出异常。与 Dictionary 索引器不同,如果字典中已存在具有给定键的元素,TryAdd 不会覆盖该元素。如果键已存在,TryAdd 不执行任何操作并返回 false。

TryGetValue 此方法结合了 ContainsKey 方法和 Item [ ] 属性的功能。

如果未找到该键,则 值 参数会获得类型 T值 的相应默认值;例如,整数类型的默认值为 0(零),布尔类型的默认值为 false,引用类型的默认值为 null。

如果你的代码经常尝试访问字典中不存在的键,请使用 TryGetValue 方法。使用此方法比捕获 Item [ ] 属性抛出的 KeyNotFoundException 更高效。

此方法的操作复杂度接近 O(1)。

标签: none

添加新评论