从这个小案例我学到了不少知识。这些无论如何无法从书里得来。正所谓实践出真知,学习编程需要大量实践这句话永不过时。
首先:好的代码和坏的代码带来的性能上的差异很明显。好的策略可以让你的程序运行速度大大加快。而差的代码则能让你的程序直接卡死。
这是我写的递归填充TreeView:
private void GetNode1(TreeNode tNod, int id) { using (SqlConnection conn = new SqlConnection("server=.\\sqlexpress;database=WebSite;uid=sa;pwd=123456")) { using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = "select ar_id,ar_name,ar_uid from Area where ar_uid="+id; conn.Open(); SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { TreeNode newTNod = new TreeNode(dr.GetString(1)); GetNode1(newTNod, dr.GetInt32(0)); tNod.Nodes.Add(newTNod); } } } }
运行程序,等了不下10秒界面才出。原因是执行查询次数太多,sqlconnection本身就耗费较大的资源。并且dr的结果集放在服务器每次去取,也很耗时。搞不好就是死递归,对服务器资源极大的浪费
改进后:
using System; using System.Collections.Generic; using System.Windows.Forms; using System.Data.SqlClient; namespace TreeView控件 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private List<Area> list = new List<Area>(); private void Form1_Load(object sender, EventArgs e) { using (SqlConnection conn = new SqlConnection("server=.\\sqlexpress;database=WebSite;uid=sa;pwd=123456")) { using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = "select ar_id,ar_name,ar_uid from Area"; conn.Open(); SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { list.Add(new Area { ar_id = dr.GetInt32(0), ar_name = dr.GetString(1), ar_uid = dr.GetInt32(2) }); } } } TreeNode t = new TreeNode("全国"); GetNode(t, 0); TreeView.Nodes.Add(t); } private void GetNode(TreeNode tNod, int id) { foreach (Area item in list) { if (item.ar_uid == id) { TreeNode newTNow = new TreeNode(item.ar_name); GetNode(newTNow, item.ar_id); tNod.Nodes.Add(newTNow); } } } } }
先一次性从数据库中取出数据,存放到list<>泛型集合,然后对list操作。这样速度快效率高。值得借鉴!
总结一下我对递归的理解:递归就是调用和自己代码相同的方法。不能把它理解为调用自己。