使用 Linq to 对象,如何轻松创建<字符串、字符串>的空字典
本文关键字:字符串 字典 创建 to Linq 对象 何轻松 使用 | 更新日期: 2023-09-27 18:32:58
要创建一个空序列,请使用以下内容
var empty = Enumerable.Empty<string> ();
有没有像这样容易地创建空字典的等效项?
回到2019年,有一种方法可以实现这一点,使用:
ImmutableDictionary<TKey, TValue>.Empty
更多信息可以在这里找到(最后几篇文章(: https://github.com/dotnet/corefx/issues/25023
没有等价物...
Enumerable.Empty<T>()
的目的是返回空数组的"缓存"实例。因此,您可以避免创建新数组(return new T[0];
(的开销。
您不能将其转换为非只读结构,如IDictionary<TKey, TValue>
或Dictionary<TKey, TValue>
,因为返回的实例可能会在以后被修改,因此会使目的无效...
new Dictionary<string, string>()
怎么了?
我假设(至少现在 5 年后(空字典实际上意味着空的只读字典。此结构与空的可枚举序列一样有用。例如,您可能有一个具有字典属性(例如 JSON(的配置类型,一旦配置就无法修改:
public class MyConfiguration
{
public IReadOnlyDictionary<string, string> MyProperty { get; set; }
}
但是,如果从未配置该属性,该怎么办?那么MyProperty
就null
了.避免意外NullReferenceException
的一个好解决方案是使用空字典初始化属性:
public class MyConfiguration
{
public IReadOnlyDictionary<string, string> MyProperty { get; set; }
= new Dictionary<string, string>();
}
缺点是每次分配MyConfiguration
都需要分配一个空字典。为了避免这种情况,你需要类似于Enumerable.Empty<T>()
的东西,即缓存的空只读字典。
有两种方法可以实现此目的。第一种是依赖于System.Collections.Immutable。ImmutableDictionary<TKey, TValue>
实现IReadOnlyDictionary<TKey, TValue>
,它有一个可以使用的Empty
字段:
IReadOnlyDictionary<string, string> empty = ImmutableDictionary<string, string>.Empty;
或者,您可以实现自己的空只读字典,类似于 Enumerable.Empty<T>()
和 Array.Empty<T>()
。请注意,空值不再是字段,并且该类不是泛型的。相反,它是一种通用方法。这需要两个类。
第一个类是"隐藏的",可以是内部的:
internal static class EmptyReadOnlyDictionary<TKey, TValue>
{
public static readonly IReadOnlyDictionary<TKey, TValue> Instance
= new Dictionary<TKey, TValue>();
}
第二个类使用第一个类,但将其隐藏在IReadOnlyDictionary<TKey, TValue>
接口后面:
public static class ReadOnlyDictionary
{
public static IReadOnlyDictionary<TKey, TValue> Empty<TKey, TValue>()
=> EmptyReadOnlyDictionary<TKey, TValue>.Instance;
}
用法:
IReadOnlyDictionary<string, string> empty = ReadOnlyDictionary.Empty<string, string>();
对于这两种解决方案,对于 TKey
和 TValue
的每个不同组合,只有一个空字典实例。
在 .NET 8 预览版中,可以通过以下方式创建空Dictionary
:
ReadOnlyDictionary<TKey, TValue>.Empty;
这种方式不使用内存,并且比使用 new
关键字启动它更快。
当键和值具有相同的类型(例如:字符串(时:
Enumerable.Empty<string>().ToDictionary(x=>x, x=>x)
Enumerable.Empty<KeyValuePair<string, object>>().ToDictionary(kvp => kvp.Key, kvp => kvp.Value)