I want to know understand the way the object creation/referencing is happening. I have a piece of code where all Employee objects in my list are duplicated. The top code has the issue that overrides all previous entries so the list contains duplicated objects whereas the bottom was my fix. I want to understand why creating the new object inside the while.Read() loop worked whereas having the employee object creation outside of the while loop did not.
我想知道对象创建/引用的发生方式。我有一段代码,其中列表中的所有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;
}
}
I want to understand why this fixed the issue.
我想了解为什么这解决了这个问题。
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;
}
}
2 个解决方案
#1
1
In your first example, you have a single _employee
object, created outside the loop. This object is stored in a single reference in memory. When you use Add(_employee)
, you are not creating a new object with the current properties of the _employee
, you are adding the reference to that single object in memory to the list, multiple times. When you change the value of any of the properties of _employee
on subsequent trips through the loop, you are changing that single object in memory, which is, in effect, changing every item in the list.
在第一个示例中,您有一个在循环外创建的_employee对象。该对象存储在内存中的单个引用中。使用Add(_employee)时,您不是使用_employee的当前属性创建新对象,而是将对内存中该单个对象的引用多次添加到列表中。当您在循环的后续行程中更改_employee的任何属性的值时,您正在更改内存中的单个对象,这实际上是更改列表中的每个项目。
In the second example, you are creating a new _employee
object every loop through the while
, and each new object has a new memory address. Therefore, every object you add in to the list is independent of the last.
在第二个示例中,您将在每个循环中创建一个新的_employee对象,并且每个新对象都有一个新的内存地址。因此,您添加到列表中的每个对象都独立于最后一个。
#2
0
Typeof Employee
is a Reference Type which is just a pointer to another memory location that holds the real data.
Typeof Employee是一个引用类型,它只是指向保存实际数据的另一个内存位置的指针。
In the first example you are only initializing one instance of Employee
(a reference type). In the while
loop you keep adding that same instance to the collection, and at the same time update its properties (all the items in the collection will have their properties set the the values of the last row in the database).
在第一个示例中,您只是初始化一个Employee实例(引用类型)。在while循环中,您不断将相同的实例添加到集合中,同时更新其属性(集合中的所有项目的属性都将设置数据库中最后一行的值)。
In the second example you create a new instance in each iteration and set its properties based on the current row. The next iteration creates another instance and sets its properties.
在第二个示例中,您将在每次迭代中创建一个新实例,并根据当前行设置其属性。下一次迭代创建另一个实例并设置其属性。
This article might help explain the difference between a reference type and a value type.
本文可能有助于解释引用类型和值类型之间的区别。
#1
1
In your first example, you have a single _employee
object, created outside the loop. This object is stored in a single reference in memory. When you use Add(_employee)
, you are not creating a new object with the current properties of the _employee
, you are adding the reference to that single object in memory to the list, multiple times. When you change the value of any of the properties of _employee
on subsequent trips through the loop, you are changing that single object in memory, which is, in effect, changing every item in the list.
在第一个示例中,您有一个在循环外创建的_employee对象。该对象存储在内存中的单个引用中。使用Add(_employee)时,您不是使用_employee的当前属性创建新对象,而是将对内存中该单个对象的引用多次添加到列表中。当您在循环的后续行程中更改_employee的任何属性的值时,您正在更改内存中的单个对象,这实际上是更改列表中的每个项目。
In the second example, you are creating a new _employee
object every loop through the while
, and each new object has a new memory address. Therefore, every object you add in to the list is independent of the last.
在第二个示例中,您将在每个循环中创建一个新的_employee对象,并且每个新对象都有一个新的内存地址。因此,您添加到列表中的每个对象都独立于最后一个。
#2
0
Typeof Employee
is a Reference Type which is just a pointer to another memory location that holds the real data.
Typeof Employee是一个引用类型,它只是指向保存实际数据的另一个内存位置的指针。
In the first example you are only initializing one instance of Employee
(a reference type). In the while
loop you keep adding that same instance to the collection, and at the same time update its properties (all the items in the collection will have their properties set the the values of the last row in the database).
在第一个示例中,您只是初始化一个Employee实例(引用类型)。在while循环中,您不断将相同的实例添加到集合中,同时更新其属性(集合中的所有项目的属性都将设置数据库中最后一行的值)。
In the second example you create a new instance in each iteration and set its properties based on the current row. The next iteration creates another instance and sets its properties.
在第二个示例中,您将在每次迭代中创建一个新实例,并根据当前行设置其属性。下一次迭代创建另一个实例并设置其属性。
This article might help explain the difference between a reference type and a value type.
本文可能有助于解释引用类型和值类型之间的区别。