可空类型和.HasValue仍会抛出Null异常

3

我有一个描述存储的各种手机的类。有时Importance属性可能为null。以下是该类:

public class PhoneTypeListInfo
{
    public string AccountNum { get; set; }
    public int PhoneType { get; set; }
    public string PhoneNum { get; set; }

    public int Importance { get; set; }
}

我定义了一个函数,如果电话号码和账户号码匹配给定的一组值,它将返回一个PhoneTypeListInfo

    protected PhoneTypeListInfo RetrievePhoneType(string info, string acctNumber)
    {
        PhoneTypeListInfo type = xPhoneTypeList.Where(p => p.PhoneNum == info && p.AccountNum == acctNumber).FirstOrDefault();

        return type;
    }

这一切都很好。我的问题在于下面的linq查询。

List<AlertBasedPhones> xAccountPhones = new List<AlertBasedPhones>();
xAccountPhones = (from x in xAccountStuff
                  where x.Media == "Phone"
                  let p = RetrievePhoneType(x.Info, acct.AccountNumber)
                  let xyz = x.Importance = (p.Importance as int?).HasValue ? p.Importance : 0
                  orderby p.Importance descending
                  select x).ToList();

我上面所做的是尝试使用一个不同构成的类,除了从PhoneTypeListInfo获取'Importance'属性以外。
我的问题最终是,我需要做什么才能允许

p.Importance

为空,并将它设置为0,如果它为空,则使x.Importance也为0。

2
我认为空的不是 p.Importannce,而是 p 本身。 - Scott Chamberlain
我认为Scott是对的,你需要额外检查RetrievePhoneType是否返回了null以及p本身。 - Mong Zhu
空值传播运算符“?. ”在这里可能很有用。 - Volker Schmidt
由于“importance”不是可空整数,因此这个表达式:“(p.Importance as int?)。HasValue”始终为真。 - Mong Zhu
2个回答

6

p.Importannce并不是空的,而是p本身为空。你需要先检查它是否为空。如果你正在使用C# 6,可以使用?.运算符。你也可以简化逻辑(p.Importance as int?).HasValue ? p.Importance : 0p.Importance ?? 0。将两者结合起来,你就可以得到:

List<AlertBasedPhones> xAccountPhones = new List<AlertBasedPhones>();
xAccountPhones = (from x in xAccountStuff
                         where x.Media == "Phone"
                         let p = RetrievePhoneType(x.Info, acct.AccountNumber)
                         let xyz = x.Importance = p?.Importance ?? 0
                         orderby p?.Importance descending
                         select x).ToList();

p 不为 null。我会测试 Robert 的答案,但看起来我应该使用三元运算符。 - Chris Clark
如果0行匹配xPhoneTypeList.Where(p => p.PhoneNum == info && p.AccountNum == acctNumber),那么p将为null。Robert的答案使用(null==p)进行了相同的空值检查,我只是使用了C#6中引入的更方便的?.运算符。 - Scott Chamberlain
@ChrisClark 如果你很有信心从不会出现 xPhoneTypeList.Where(p => p.PhoneNum == info && p.AccountNum == acctNumber) 返回 0 行数据的情况,那么请将 .FirstOrDefault() 改为 .First(),这样如果有 0 行数据,就会抛出异常(但如果永远不会出现 0 行数据,这不会是个问题)。 - Scott Chamberlain
我明白你的意思。我使用三元运算符,因为这不是C# 6.0。 - Chris Clark
我将此标记为答案,因为如果我有C# 6.0,我确信这将会起作用。我将 orderby p?.Importance descending 更改为 x.Importance descending ,并使用 x.Importance = (p == null) ? 0 : p.Importance 代替。 - Chris Clark

2
使用三目运算符。将 p.Importance 替换为 (null==p) ? 0 : p.Importance

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接