【问题标题】:C# - avoid null pointers in LINQ ToDictionaryC# - 避免 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”

【问题讨论】:

    标签: c# linq dictionary


    【解决方案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 的建议 - 最好不要出现编译时错误,但我仍然会收到警告(我已更新我的帖子以包含该信息)跨度>
    猜你喜欢
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多