2009-08-11 80 views
4

假設我有三個類A,B和C,它們嵌套的方式使我可以通過A訪問C到B(即A.B.C)。如果我試圖訪問C的一個簡單屬性,比如說Id類型int,並且我沒有在A中創建B的新實例(或B中的C),我會得到一個'Object reference not set to an instance of一個東西。'錯誤。未將對象引用設置爲對象的實例。 - DefaultValue

我想知道的是,如果有一種簡單的方式說讓我A.B.C.Id,並且如果你不能在某種程度上產生一個空值,那麼給我一個默認值。

var myId = A.B.C.Id <some operator> -1; 

目前我正在做這樣的事情,它感覺很糟糕。

var myId = A == null ? -1 : A.B == null ? -1 : A.B.C == null ? -1 : A.B.C.Id; 

回答

2

在C#中沒有特別的語法可以做你想做的事情。

但是有一些架構方式,如何去做。

您可以使用Null Object Design Pattern 或可以延長A,B,C類與擴展方法,它允許空值:如果你必須去那深藏在你可能想創建一個屬性

​​
+1

爲什麼downwote? – TcKs 2009-08-11 14:37:50

+0

我接受這個作爲我的問題的答案,因爲事實上TcK已經盡最大努力爲我的情況提供解決方案。我在一個理想的世界裏感知,我會重構並擺脫這種情況,但不幸我不在那​​裏工作:)。 – voiddog 2009-08-14 09:20:35

1

查找到dependency injection這將在A B和B創建C當你答的新實例,或者只是將代碼放在你的類的構造函數來創建這樣的實例。 (所以在A()中創建B和在B()中創建C)

它感覺錯誤的原因是,正如其他人指出的那樣,您不應該處於發生這種情況的情況。

+0

刪除代碼示例,因爲它是錯誤的BTW – Damien 2009-08-11 13:50:05

+0

如何解決依賴注入與空值的問題? – TcKs 2009-08-11 13:53:25

+1

它不會解決ID爲空的問題,但它將解決從屬類(在這種情況下,B和C)爲空的問題,因爲它們將使用A創建。 – Damien 2009-08-11 13:58:14

4

通過經過A或B或兩者都打破了Law of Demeter這是不好的做法。如果需要以某種方式引用某個東西,則需要一個空的構造函數來構建這種連接。

+0

取決於你對德米特法的解釋的嚴格性。 'person.Name.FirstName','person.Name.LastName'是否違反了Law?我想大多數人不會那麼嚴格。 – Ruben 2009-08-11 14:21:53

+0

我認爲他意味着邏輯類。任何包含我猜想的方法的東西。我不知道有一個書面規則+1; – Damien 2009-08-11 14:27:55

+0

@Ruben德米特定律可以被打破,有時它可以打破,但如果你打破它,我會建議看看你的結構,看看你是否可以構造你的對象,這樣你就不會因爲你越少違反定律demeter越有可能你的代碼會被測試,因爲你可以將更多的依賴關係注入到它中。 – AutomatedTester 2009-08-11 14:34:48

1

在A中給你null或BCId。

+0

我會說更深入: 答:我得到{返回B == null? -1:B.I} B.I get {return C == null? -1:C.I} 但這不是一個選項,如果你有很多屬性 – Toto 2009-08-12 08:42:02

-2

你可以試試這個代碼:

var myId = -1; 
try 
{ 
    myId = A.B.C.Id; 
} 
catch (NullReferenceException e) 
{ 
    myId = -1; 
} 
+2

-1這是非常糟糕的方式,如何做到這一點。 它會使程序變得緩慢,如果經常會拋出異常,調試將變得更加困難。 – TcKs 2009-08-11 13:52:16

+3

使用異常來控制程序流是不好的做法。在這種情況下,您可以輕鬆檢查空值以避免引發異常。 – 2009-08-11 13:53:27

+2

請勿將異常用作控制流。您的代碼將更具可讀性,並且可以維護,如果您拼寫出空的檢查。 – 2009-08-11 13:56:34

1

這是一個非常適合的Null Object設計模式。

基本上,定義NullB這樣的:

public class NullB : B 
{ 
    public override C C 
    { 
     get { return new NullC(); } 
    } 
} 

然後正是如此定義NullC:

public class NullC : C 
{ 
    public override int Id 
    { 
     get { return 0; } 
    } 
} 

這顯然需要有問題的類有虛擬成員,但它是更安全的方式。然後,當你有B和C的實例時,你只需使用並返回它們。

0

您可以使用屬性來檢查請求的類是否爲null。如果是,它將創建該類的新實例。

class ClassA 
{ 
    private ClassB m_ClassB = null; 
    public ClassB B 
    { 
     get 
     { 
      //check if we already have an instance of the class. 
      //if not create it 
      if (m_ClassB == null) 
      { 
       m_ClassB = new ClassB(); 
      } 
      return m_ClassB; 
     } 
    } 
} 

class ClassB 
{ 
    private ClassC m_ClassC = null; 
    public ClassC C 
    { 
     get 
     { 
      //check if we already have an instance of the class. 
      //if not create it 
      if (m_ClassC == null) 
      { 
       m_ClassC = new ClassC(); 
      } 
      return m_ClassC; 
     } 
    } 
} 

class ClassC 
{ 
    private int m_Id = 123; 
    public int ID 
    { 
     get 
     { 
      return m_Id; 
     } 
    } 
} 

然後,你可以訪問你所需要的是這樣

CLassA A = new ClassA(); 
int id = A.B.C.ID; 
相關問題