C# - 避免 LINQ ToDictionary 中的空指针

Posted

技术标签:

【中文标题】C# - 避免 LINQ ToDictionary 中的空指针【英文标题】:C# - avoid null pointers in LINQ ToDictionary 【发布时间】:2021-04-25 08:16:30 【问题描述】:

我有一个这样的对象:

class Moose

   public int? DatabaseID;   // (null if not stored)
   public string Name;


List<moose> meese;

我想为那些具有非空 DatabaseID 的 meese 生成一个将 DatabaseID 映射到 Name 的字典。

直达路线不起作用:

Dictionary<int, string> mapIdToName = meese.Where(moose => moose.DatabaseID != null).ToDictionary(moose => moose.DatabaseID, moose => moose.Name);

我明白了

Cannot implicitly convert type 'System.Collections.Generic.Dictionary<int?, string>' to 'System.Collections.Generic.Dictionary<int, string>'

如果我要创建一个列表,我可以这样做:

List<int> databaseIDs = meese.Select(moose => moose.DatabaseID).OfType<int>();

但我找不到与 ToDictionary 类似的内容。

现在我只是手动操作:

Dictionary<int, string> mapIdToName = new Dictionary<int, string>();
foreach (var moose in meese)

   if (moose.DatabaseID != null)
      mapIdToName[moose.DatabaseID] = moose.Name;

有没有聪明的 Linq 方法来做到这一点?

编辑

我有

#nullable enable

这样做

Dictionary<int, string> mapIdToName = meese.Where(moose => moose.DatabaseID.HasValue).ToDictionary(moose => moose.DatabaseID.Value, moose => moose.Name);

不会产生错误,但会产生警告“Nullable value type may be null”

【问题讨论】:

【参考方案1】:

你可以的

var map = meese.Where(moose => moose.DatabaseID.HasValue).ToDictionary(moose => moose.DatabaseID!.Value, moose => moose.Name);

注意DatabaseID 之后的!dammit operatornull forgiving operator,你基本上会告诉编译器我知道的事实是这不是null,所以请注意。

【讨论】:

哦,我讨厌该死的运算符(它尝起来像输了),但这可能是必要的情况 GetValueOrDefault【参考方案2】:

第一次尝试时,您几乎成功了。将 Nullable 类型映射到其基类型时,您需要记住将值拆箱。应该是这样的:

Dictionary<int, string> mapIdToName = meese.Where(moose => moose.DatabaseID.HasValue).ToDictionary(moose => moose.DatabaseID.Value, moose => moose.Name);

【讨论】:

确实越来越近了,起初我没有意识到启用 NRT 会改变一些事情,所以我编辑了我的原始帖子。编译器确实接受了这一点,阅读它的人会同意它是正确的,但编译器仍然很紧张(给我一个警告)moose.DatabaseID.Value 可能为空 我认为根本问题是 Where() 返回的类型与它给出的相同,所以即使在我们人类实现的 Where() 过滤掉空值之后,类型仍然是 Dictionary 只需指定 ID.Value,例如 `meese.Where(a=>a.DatabaseID.HasValue).ToDictionary(a=>a.DatabaseID.Value, b=>b.Name)` 是的,这就是 greenjaed 的建议 - 最好不要出现编译时错误,但我仍然会收到警告(我已更新我的帖子以包含该信息)跨度>

以上是关于C# - 避免 LINQ ToDictionary 中的空指针的主要内容,如果未能解决你的问题,请参考以下文章

Linq ToDictionary 匿名与具体类型 [重复]

Enumerable.ToDictionary 是不是只检索它需要的内容?

将 DataTable 转换为字典 C#

请问下,C#的泛型数组中的 ToDictionary 方法怎么用? 详细说明请进。。

为啥 C# 编译器在使用 LINQ 方法 Any() 时会创建私有 DisplayClass,我该如何避免它?

编写高质量代码改善C#程序的157个建议——建议31:在LINQ查询中避免不必要的迭代