2011-12-13 103 views
1

我正在使用對象樹的遞歸函數。也就是說,我的對象集合是這樣的:動態派生類型參數

Object1 
--Object2 
----Object3 
------Object4 

所有對象從基本對象(抽象類),其中有一個validate()方法繼承,其收集來自ITreeCollection繼承。我已經寫了一個遞歸函數來執行:

private bool Validate<T>(ITreeCollection items) where T : TreeNodeBase 
     { 
      foreach (var itm in items as Collection<T>) 
      { 
       if (((TreeNodeBase)itm).Items != null) 
       { 
        return Validate<T>(((TreeNodeBase)itm).Items); 
       } 
       else return true; 
      } 
      return true; 
     } 

我如何可以推導出類型參數T的內部函數(即return Validate<T>(((TreeNodeBase)itm).Items)

+1

邊注:避免'as'投,如果情況下,你不立即檢查空當你轉換一個完全理解的轉換異常成空裁判例外,經常在代碼網站unrelate d演員。 –

+1

另一方面說明:在驗證項目列表中的第一個項目之後,您的循環會返回。我想如果'Validate'返回false,那麼你只想返回,以便剩下的項目得到驗證。就目前而言,你會在第一片葉子上得到結果。 –

+2

看起來你不需要任何泛型:用'TreeNodeBase'替換'T',事情就會起作用。 – dasblinkenlight

回答

2

首先,因爲它的立場,你不使用的類型參數T,以便它可以安全地被刪除。不過,我想你可能想要做一些類型特定的驗證,所以這可能不是一個有用的建議。但是,沒有你想要用T做什麼的例子,很難提出建議。

總之,這裏是什麼,我認爲你正在嘗試做的一種方法:

private bool Validate(ITreeCollection items) 
{ 
    foreach (TreeNodeBase node in (IEnumerable) items) 
    { 
     // validate the node itself first 
     if (!Validate(node)) 
     { 
      return false; 
     } 

     if (node.Items != null) 
     { 
      // validate its children 
      if (!Validate(node.Items) 
      { 
       return false; 
      } 
     } 
    } 

    return true; 
} 

private bool Validate(TreeNodeBase node) 
{ 
    if (node is BananaNode) 
    { 
     var bananaNode = (BananaNode) node; 
     //TODO do BananaNode specific validation 
    } 
    else if (node is AppleNode) 
    { 
     var appleNode = (AppleNode) node; 
     //TODO do AppleNode specific validation 
    } 
    else 
    { 
     throw new ArgumentOutOfRangeException("Cannot validate node of type '" + node.GetType().Name + "'."); 
    } 
} 

你可以得到時髦與動態關鍵字,擺脫一些這種類型檢查的,但它確實得到了有點混亂,我建議反對:

private bool Validate(ITreeCollection items) 
{ 
    foreach (TreeNodeBase node in (IEnumerable) items) 
    { 
     // validate the node itself first 
     if (!Validate((dynamic) node)) // this will call the most appropriate version of Validate 
     { 
      return false; 
     } 

     if (node.Items != null) 
     { 
      // validate its children 
      if (!Validate(node.Items) 
      { 
       return false; 
      } 
     } 
    } 

    return true; 
} 

private bool Validate(BananaNode node) 
{ 
    //TODO do BananaNode specific validation 
} 

private bool Validate(AppleNode node) 
{ 
    //TODO do AppleNode specific validation 
} 

private bool Validate(TreeNodeBase node) 
{ 
    throw new ArgumentOutOfRangeException("Cannot validate node of type '" + node.GetType().Name + "'."); 
}