来自实际遇到的一个问题,需要查找出根节点的下的所有子节点,首先想到的就是递归了,用JS写过,C#之前写了一次没写对,这次专门用心看了一下的,发现和ref关键字有关,写贴上源码:
public static void InsertCmsTypeName(int typeid, ref List<string> cacheNameList) { string name = string.Empty; List<TB_CMSType> cts = CMS.GetCmsTypeForParentID(typeid); if (cts != null && cts.Count > 0) { foreach (TB_CMSType item in cts) { name = "GetSpecialProducts" + item.ID + Config.SiteID; cacheNameList.Add(name); InsertCmsTypeName(item.ID, ref cacheNameList); } } }
typeid是节点id,第一次是根节点,往后就是当前节点下的子节点了。cacheNameList是存储数据的集合,类型名称前面用了ref修饰。
为什么呢,这里就涉及到一个概念了,值传递!InsertCmsTypeName方法里每次对集合做add操作的时候,cacheNameList的数组个数都会新增。
List<string> cacheNameList = new List<string>(); Base.InsertCmsTypeName(4106, ref cacheNameList);
可以很明显的看到,InsertCmsTypeName方法是没有返回值的, 那么如何保持递归方法里cacheNameList的值呢,ref 就出来了,ref使参数的传递方式变成了值传递,每次参数指向的是内存里的首地址,这样每次修改这个值的时候,它本身就修改了。一般的参数传递是引用传递,就是说在传递参数的时候,参数的本身不会被修改,而通过ref修饰过的参数,传递方式变成值传递,每次方法内部修改这个参数的时候,参数的本身也会被修改,所以,InsertCmsTypeName无需返回值。
之前用C#写递归的时候就是没注意到这个,导致递归方法执行了,最后的结果还是没有 (*/ω\*) 这里记下笔记还是有必要的。
另,算法真的很重要鸭,要是不会写递归,这种通过根节点找出所有子节点的问题,怕是要写for循环了,而且就算是for循环也不能根本性解决问题,只能预测最多有多少层,然后写多少个for,麻烦的不行。当然,用递归也不能瞎用,要控制好进行递归的条件,不然很容易导致死循环的出现(这可是会卡死程序的,所以用的时候要慎用)。