2012-03-28 118 views
2

我有一個字符串屬性的類。我在閱讀時使用了coalesce操作符,因爲它可能爲空,但它仍會拋出一個NullRefrenceExeption。C#coalesce運算符拋出

string name = user.Section.ParentSection.Name ?? string.Empty; 

更具體地說,它的「.ParentSection」是空的,因爲它甚至沒有「.name」?如果是這種情況,我應該先用「if」塊測試「.ParentSection」嗎?

我假設有一些關於Coalesce操作符的東西我不明白,希望有人可以對這裏發生什麼事情有所瞭解。

+0

http://msdn.microsoft.com/en-us/library/ms173224.aspx – Rawling 2012-03-28 14:50:02

+1

正如答案所暗示的那樣,空合併運算符不會在這裏拋出;它的左操作數的評估拋出異常。 – phoog 2012-03-28 14:56:52

回答

7

更具體地說,它的「.ParentSection」爲空,因此它是 ,因爲它甚至沒有「.name」?

是的。

如果是這種情況,我應該先測試「.ParentSection」if if block?

是的。

+0

多數民衆贊成我所認爲的,但我強硬它可能是一個更優雅的解決方案。感謝:) – 2012-03-28 14:58:34

+0

有一個更優雅的解決方案稱爲Maybe Monad。看到我的答案。 – FishBasketGordo 2012-03-28 15:00:24

3

您需要檢查是否useruser.Sectionuser.Section.ParentSection爲空,然後才能對user.Section.ParentSection的屬性使用空合併運算符。

3

如果任何訪問的對象是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。首先,一些重構可能會使這不必要。

+0

我同意; '公共字符串getParentSectionName()'將是一個受歡迎的變化,我敢肯定。 – 2012-03-28 14:56:40

1

可能是useruser.Sectionuser.Section.ParentSection是空值。

??運營商並不能阻止類似的檢查:

if (user != null && user.Section != null && user.Section.ParentSection != null){ 

確保一切到字符串屬性是有效的存在,那麼你可以使用??。不管你嘗試了多少次,你都不能撥打(null).Name

2

??運算符檢查左側是否爲空,如果是,則返回右側,如果不是左側,則返回右側。 在你的情況下,左側是對象user.Section.ParentSection中的「Name」屬性,它是空的。

在這種情況下,不是想上什麼可能爲空或做這樣的事情:

string name = user == null 
       || user.Section == null 
       || user.ParentSection == null 
       || user.Section.ParentSection.Name == null 
       ? string.Empty 
       : user.Section.ParentSection.Name; 

(是的,它的醜陋,我知道)

0

是的,你需要檢查是否SectionParentSection之前爲空你檢查Name

0

這可能是最好做這樣的事情:

if(user!=null && user.Section!=null && user.Section.ParentSection!=null) 
{ 
    string name = user.Section.ParentSection.Name ?? string.Empty; 
} 
4

您需要檢查SectionParentSection是否爲空。你可以使用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

+0

謝謝,我會檢查一下。 – 2012-03-28 15:06:40

0

空合併運算符采取如下語句:

a = b ?? c; 

它說的是「評估B;如果它有一個非空值,然後分配到否則將c的值賦給一個「。

但是內 B您正在使用的可能爲null具有部分對象,可以爲null有可能是空的是有一個名字屬性,可以爲null父部分屬性的用戶對象。如果您想檢查所有的這些(通常你應該),那麼你可以這樣做:

string name = string.Empty; 
if (user != null && 
    user.Section != null && 
    user.Section.ParentSection != null) 
{ 
    name = user.Section.ParentSection.Name ?? string.Empty; 
} 

只要IF檢查失敗也不會進一步檢查,因此你沒有得到一個NullReferenceException時你假定有一個對象存在,然後嘗試訪問它的一個屬性。