C# 合并运算符抛出
Posted
技术标签:
【中文标题】C# 合并运算符抛出【英文标题】:C# coalesce operator Throws 【发布时间】:2012-04-12 04:38:45 【问题描述】:我有一个带有字符串属性的类。我在读取它时使用了 coalesce 运算符,因为它可能为 null,但它仍然会抛出 NullRefrenceExeption。
string name = user.Section.ParentSection.Name ?? string.Empty;
更具体地说,它的“.ParentSection”是空的,是不是因为它甚至没有“.name”?如果是这种情况,我应该先用 if 块测试“.ParentSection”吗?
我认为 Coalesce 操作员有一些我不明白的地方,希望有人能解释一下这里出了什么问题。
【问题讨论】:
msdn.microsoft.com/en-us/library/ms173224.aspx 正如答案所暗示的那样,空合并运算符不会在这里抛出;引发异常的是对其左操作数的求值。 【参考方案1】:更具体地说,它的“.ParentSection”是空的,所以它也是 因为它甚至没有“.name”?
是的。
如果是这种情况,我应该先用 if 测试“.ParentSection” 屏蔽?
是的。
【讨论】:
这就是我的假设,但我坚持认为这可能是一个更优雅的解决方案。谢谢:) 有一个更优雅的解决方案,叫做 Maybe Monad。看我的回答。【参考方案2】:您需要检查 Section
和 ParentSection
是否为空。您可以为此使用 if 语句或编写如下扩展方法:
public static class MaybeMonad
public static TOut With<TIn, TOut>(this TIn input, Func<TIn, TOut> evaluator)
where TIn : class
where TOut : class
if (input == null)
return null;
else
return evaluator(input);
你会像这样使用这个方法:
string name = user.With(u => u.Section)
.With(s => s.ParentSection)
.With(p => p.Name) ?? string.Empty;
我认为它比包含大量 &&
的 if 语句要干净得多。
进一步阅读:http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad
【讨论】:
谢谢,我去看看。【参考方案3】:您需要先检查user
、user.Section
或user.Section.ParentSection
是否为空,然后才能对user.Section.ParentSection
的属性使用空合并运算符。
【讨论】:
【参考方案4】:如果访问的任何对象是null
,则嵌套属性访问是不安全的,这将引发NullReferenceException
。您必须显式测试外部对象是否不为空。
例如:
string name = string.Empty;
if(user!=null && user.Section!=null && user.Section.ParentSection !=null)
name = user.Section.ParentSection.Name ?? string.Empty;
一般来说,我会尽量避免嵌套访问属性,你违反了Law of Demeter。一些重构可能首先使这变得不必要。
【讨论】:
我同意;public String getParentSectionName()
我敢肯定,这将是一个受欢迎的变化。【参考方案5】:
??
运算符检查左侧是否为空,如果是则返回右侧,如果不是左侧。
在您的情况下,左侧是对象 user.Section.ParentSection
中的“名称”属性,这是 null。
在这些情况下,要么考虑可能为 null 的内容,要么执行以下操作:
string name = user == null
|| user.Section == null
|| user.ParentSection == null
|| user.Section.ParentSection.Name == null
? string.Empty
: user.Section.ParentSection.Name;
(是的,我知道它很丑)
【讨论】:
【参考方案6】:user
或 user.Section
或 user.Section.ParentSection
可能为空值。
??
运算符不会阻止以下检查:
if (user != null && user.Section != null && user.Section.ParentSection != null)
确保字符串属性之前的所有内容都有效且存在,然后您可以使用??
。无论您尝试多少次,都无法拨打(null).Name
。
【讨论】:
【参考方案7】:是的,您需要在检查 Name
之前检查 Section
或 ParentSection
是否为空
【讨论】:
【参考方案8】:最好这样做:
if(user!=null && user.Section!=null && user.Section.ParentSection!=null)
string name = user.Section.ParentSection.Name ?? string.Empty;
【讨论】:
【参考方案9】:空合并运算符采用如下语句:
a = b ?? c;
这说的是“评估 b;如果它有一个非空值,则将其分配给 a。否则将 c 的值分配给 a”。
但是,在 your b 中,您使用的用户对象可能为 null,其 section 对象可能为 null,其父 section 属性可能为 null,其 name 属性为可能为空。如果您想检查所有这些(通常您应该),那么您可以执行以下操作:
string name = string.Empty;
if (user != null &&
user.Section != null &&
user.Section.ParentSection != null)
name = user.Section.ParentSection.Name ?? string.Empty;
一旦 IF 检查失败,它将不会进一步检查,因此当您假设对象存在并尝试访问其属性之一时,您不会收到 NullReferenceException。
【讨论】:
以上是关于C# 合并运算符抛出的主要内容,如果未能解决你的问题,请参考以下文章