2015-03-29 2 views
-1

Я хочу знать, как происходит создание/ссылка на объект. У меня есть фрагмент кода, в котором все объекты Employee в моем списке дублируются. В верхнем коде есть проблема, которая отменяет все предыдущие записи, поэтому список содержит дублированные объекты, тогда как нижняя часть - мое исправление. Я хочу понять, почему создание нового объекта внутри цикла while.Read() работало, тогда как создание объекта employee за пределами цикла 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; 
       } 
      } 

ответ

2

В первом примере, у вас есть один _employee объект, созданный за пределами цикла. Этот объект хранится в одной ссылке в памяти. Когда вы используете Add(_employee), вы не создаете новый объект с текущими свойствами _employee, вы добавляете ссылку на этот единственный объект в памяти в список несколько раз. Когда вы изменяете значение любого из свойств _employee при последующих поездках по циклу, вы меняете этот единственный объект в памяти, который, по сути, меняет каждый элемент в списке.

Во втором примере вы создаете новый объект _employee каждый цикл через while, и каждый новый объект имеет новый адрес памяти. Поэтому каждый объект, который вы добавляете в список, не зависит от последнего.

1

Тип Employee - это ссылочный тип, который является указателем на другую ячейку памяти, содержащую реальные данные.

В первом примере вы только инициализируете один экземпляр Employee (ссылочный тип). В цикле while вы продолжаете добавлять тот же экземпляр в коллекцию и одновременно обновлять его свойства (все элементы коллекции будут иметь свои свойства, задающие значения последней строки в базе данных).

Во втором примере вы создаете новый экземпляр на каждой итерации и устанавливаете его свойства на основе текущей строки. Следующая итерация создает другой экземпляр и устанавливает его свойства.

This article может помочь объяснить разницу между ссылочным типом и типом значения.

Смежные вопросы