我想知道对象创建/引用的发生方式。我有一段代码,其中列表中的所有Employee对象都是重复的。顶级代码的问题是覆盖所有以前的条目,因此列表包含重复的对象,而底部是我的修复。我想了解为什么在while.Read()循环中创建新对象,而在while循环之外创建雇员对象却没有。
public IEnumerable<Employee> Employees
{
get
{
List<Employee> employees = new List<Employee>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
Employee _employee = new Employee(); //<issue is here, all enties in employees are duplicated values of a single record
SqlCommand sqlCmd = new SqlCommand("spGetAllEmployees", connection);
sqlCmd.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
SqlDataReader reader = sqlCmd.ExecuteReader();
while (reader.Read())
{
_employee.EmployeeID = Convert.ToInt32(reader["EmployeeID"]); //object instantiation here fixed the issue, why?
_employee.Name = (reader["Name"].ToString());
_employee.Gender = (reader["Gender"].ToString());
_employee.City = (reader["City"].ToString());
_employee.DateOfBirth = Convert.ToDateTime(reader["DateOfBirth"]);
_employee.DepartmentID = Convert.ToInt32(reader["DepartmentID"]);
employees.Add(_employee);
}
}
return employees;
}
}
我想了解为什么这样可以解决问题。
public IEnumerable<Employee> Employees
{
get
{
List<Employee> employees = new List<Employee>();
using (SqlConnection connection = new
SqlConnection(connectionString))
{
SqlCommand sqlCmd = new SqlCommand("spGetAllEmployees", connection);
sqlCmd.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
SqlDataReader reader = sqlCmd.ExecuteReader();
while (reader.Read())
{
Employee _employee = new Employee(); //this fixed the issue, why?
_employee.EmployeeID = Convert.ToInt32(reader["EmployeeID"]);
_employee.Name = (reader["Name"].ToString());
_employee.Gender = (reader["Gender"].ToString());
_employee.City = (reader["City"].ToString());
_employee.DateOfBirth = Convert.ToDateTime(reader["DateOfBirth"]);
_employee.DepartmentID = Convert.ToInt32(reader["DepartmentID"]);
employees.Add(_employee);
}
}
return employees;
}
}
答案 0 :(得分:1)
在第一个示例中,您在循环外部创建了一个_employee
对象。该对象存储在内存中的单个引用中。当您使用Add(_employee)
时,您没有使用_employee
的当前属性创建新对象,而是将多个内存中的单个对象的引用添加到列表中。当您在循环中的后续行程中更改_employee
的任何属性的值时,您正在更改内存中的单个对象,这实际上是更改列表中的每个项目。
在第二个示例中,您将通过_employee
每次循环创建一个新的while
对象,并且每个新对象都有一个新的内存地址。因此,您添加到列表中的每个对象都独立于最后一个。
答案 1 :(得分:0)
Typeof Employee
是一个引用类型,它只是指向保存实际数据的另一个内存位置的指针。
在第一个示例中,您只是初始化一个Employee
实例(引用类型)。在while
循环中,您继续将相同的实例添加到集合中,同时更新其属性(集合中的所有项目的属性都将设置数据库中最后一行的值)。
在第二个示例中,您将在每次迭代中创建一个新实例,并根据当前行设置其属性。下一次迭代创建另一个实例并设置其属性。
This article可能有助于解释引用类型和值类型之间的区别。