从这个小案例我学到了不少知识。这些无论如何无法从书里得来。正所谓实践出真知,学习编程需要大量实践这句话永不过时。
首先:好的代码和坏的代码带来的性能上的差异很明显。好的策略可以让你的程序运行速度大大加快。而差的代码则能让你的程序直接卡死。
这是我写的递归填充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操作。这样速度快效率高。值得借鉴!
总结一下我对递归的理解:递归就是调用和自己代码相同的方法。不能把它理解为调用自己。