代码问题排查:为何从SQL获取的List<Menu>中菜品重复?
问题分析与解决方案
嘿,我一眼就揪出问题啦!你把Menu对象的实例化代码放在了while循环外面,这就导致整个循环过程中你一直在修改同一个对象的属性,然后反复把这个对象添加到列表里。因为C#中列表存储的是对象的引用,而不是对象本身的副本,所以最后你看到的所有菜品数据都是最后一次读取到的值——本质上列表里全是同一个Menu对象的引用,自然会全部重复。
举个简单的例子:第一次循环你给menu的Tenmon和Loaimon赋值,把它加到列表;第二次循环你又修改同一个menu的这两个属性,这时候列表里的第一个元素其实也是这个menu的引用,它的值也会跟着改变;直到循环结束,列表里的所有元素都指向这个唯一的Menu对象,显示的自然都是最后一次读取的菜品信息。
修改后的代码
把Menu的实例化移到while循环内部,每次循环都创建一个全新的对象:
public List<Menu> Getmonan() { string cs = ConfigurationManager.ConnectionStrings["RestaurantConnection"].ConnectionString; List<Menu> menulist = new List<Menu>(); using (SqlConnection conn = new SqlConnection(cs)) { SqlCommand cmd = new SqlCommand("Getmenu", conn); cmd.CommandType = CommandType.StoredProcedure; conn.Open(); SqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { // 每次循环创建新的Menu实例,避免引用重复 Menu menu = new Menu(); menu.Tenmon = reader["TenMon"].ToString(); menu.Loaimon = reader["LoaiMon"].ToString(); menulist.Add(menu); } // 可选:显式关闭DataReader,虽然using块结束时会自动处理,但显式关闭更规范 reader.Close(); } return menulist; }
额外小提示
- 确保你的
Menu类是普通的POCO(简单旧CLR对象),没有静态属性或者共享的引用类型成员,否则可能还会出现类似的状态共享问题。 - 如果你需要更高效的对象创建,也可以考虑在循环外复用对象,但每次添加前必须创建新的副本(比如通过克隆或者重新赋值新实例),不过对于这种场景,直接在循环内实例化是最清晰不易出错的方式。
内容的提问来源于stack exchange,提问作者Hau Le
相关产品推荐
相关产品推荐

