本文介绍了为什么谓词在递归函数中调用时会误解参数的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我正在尝试创建一个继承自现有winform TreeView控件的扩展树视图控件。在TreeViewEx类中创建了一个 Load()函数。在此函数中,dataSource在foreach中循环。这个foreach然后调用循环dataSource上的 Where()扩展方法,向它传递一个返回谓词的方法(以当前元素作为参数)。该谓词错误地解释了传递给它的参数值。它似乎使用了以前的参数值。 返回谓词=>之前方法中arg的值图片 [ ^ ] 当调试器输入谓词=>时, arg的值图片 [ ^ ] 我尝试过: 最初我认为这种行为是由于我正在迭代一个Enumerable而不是一个列表,所以我将不同的枚举更改为List但没有改变。还尝试将返回的谓词设置为instatiate但没有。 加载功能: public Func< T,Func< T,bool>> GetChildrenPredicate { get ; set ; } 。 。 。 public virtual void 加载(列表< T> dataSource = null ) { 尝试 { if (CreateNode == null ) { OnError?.Invoke( this , new ArgumentNullException( CreateNode)); return ; } if (GetParentKey == null ) { OnError?.Invoke( this , new ArgumentNullException( GetParentKey)); return ; } if (GetChildrenPredicate == null ) { OnError?.Invoke( this , new ArgumentNullException( GetChildrenPredicate)); return ; } var finalDataSource = dataSource ??数据源; TreeNode节点= null ; BeginUpdate(); foreach ( var item in finalDataSource) { node = CreateNode(item); node.Tag = item; if ( this .Nodes.Find(node.Name, true )。Count()== 0 ) { var n = this .Nodes.Find( this .GetParentKey( item), true )。FirstOrDefault() as TreeNode; if (n == null ) { this .Nodes.Add(node); } else { n.Nodes.Add(node); } 列表< T> children = finalDataSource .ToList() .Where( this .GetChildrenPredicate(item)) .ToList(); // this.GetChildrenPredicate // 属性func生成 // 由不同类设置的谓词 如果(children.Count()> 0 ) { // 递归调用所有childRows的此函数 Load(children); } } } EndUpdate(); } catch (例外情况) { OnError?.Invoke(这个,ex); } } GetChildrenPredicate: private Func< ORM.DataModels.Menu,bool> GetChildrenPredicate(ORM.DataModels.Menu arg) { return (ORM.DataModels.Menu m)= > (m.Lepere == arg.Codmen)|| (m.Lepere == null && arg.Codmen == _ + m.Niveau); } 解决方案 好的。我找到了解决方案。实际上我并没有意识到`finalDataSource`在每次调用`Load()`时都被覆盖了。我只专注于谓词的奇怪行为。只需使用类中定义的全局DataSource属性。 List< T> children = this .DataSource.Where( this .GetChildrenPredicate(item)); // < =将局部变量fi​​nalDataSource更改为已定义的属性this.DataSource I'm trying to create a extended treeview control inheriting from the existing winform TreeView control. Created a Load() function in the class TreeViewEx. In this function the dataSource is looped in a foreach. This foreach then calls the Where() extension method on the looping dataSource passing to it a methode (which takes as parameter the current element) returning a predicate. This predicate misintepretes the parameter value passed to it. It seems to be using previous parameter values.value of arg in method before returning predicate => Image[^]value of arg when debugger enters predicate => Image[^]What I have tried:Initially i thought this behavior was due to the fact that i am iterating through an Enumerable not a list, so i change the different enumerables to List but nothing changed. Also tried to instatiate the returned predicate but nothing.Load function :public Func<T, Func<T, bool>> GetChildrenPredicate { get; set; }...public virtual void Load(List<T> dataSource = null){ try { if (CreateNode == null) { OnError?.Invoke(this, new ArgumentNullException("CreateNode")); return; } if (GetParentKey == null) { OnError?.Invoke(this, new ArgumentNullException("GetParentKey")); return; } if (GetChildrenPredicate == null) { OnError?.Invoke(this, new ArgumentNullException("GetChildrenPredicate")); return; } var finalDataSource = dataSource ?? DataSource; TreeNode node = null; BeginUpdate(); foreach (var item in finalDataSource) { node = CreateNode(item); node.Tag = item; if (this.Nodes.Find(node.Name, true).Count() == 0) { var n = this.Nodes.Find(this.GetParentKey(item), true).FirstOrDefault() as TreeNode; if (n == null) { this.Nodes.Add(node); } else { n.Nodes.Add(node); } List<T> children = finalDataSource .ToList() .Where(this.GetChildrenPredicate(item)) .ToList(); //this.GetChildrenPredicate is //the property func generating the //predicate set by a different class if (children.Count() > 0) { // Recursively call this function for all childRows Load(children); } } } EndUpdate(); } catch (Exception ex) { OnError?.Invoke(this, ex); }}GetChildrenPredicate :private Func<ORM.DataModels.Menu, bool> GetChildrenPredicate(ORM.DataModels.Menu arg){ return (ORM.DataModels.Menu m) => (m.Lepere == arg.Codmen) || (m.Lepere == null && arg.Codmen == "_" + m.Niveau);} 解决方案 Ok. I found the solution. Actually i did not realized that `finalDataSource` was overriden on each call of `Load()`. I was only focused on the weird behaviour of the predicate. just had to used the global DataSource property defined in the class.List<T> children = this.DataSource.Where(this.GetChildrenPredicate(item)); //<= changed local variable finalDataSource to the defined property this.DataSource 这篇关于为什么谓词在递归函数中调用时会误解参数的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-22 21:00
查看更多