2011-12-13 88 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 + "'."); 
}