Почему добавление нового значения в список <> перезаписывает предыдущие значения в списке <>
Следуя нескольким учебным пособиям, я смог успешно создать класс коллекции, который наследует функции, необходимые для создания DataTable, которые могут быть переданы в хранимую процедуру Sql Server в качестве параметра значения таблицы. Кажется, что все работает хорошо; Я могу получить все добавленные строки и выглядит красиво. Однако при ближайшем рассмотрении я замечаю, что когда я добавляю новую строку, данные для всех предыдущих строк перезаписываются значением для новой строки. Поэтому, если у меня есть строка со строковым значением "foo", и я добавляю вторую строку со значением "bar", вторая строка будет вставлена (создание DataTable с двумя строками), но обе строки будут иметь значение "bar" ". Может ли кто-нибудь понять, почему это было бы? Вот некоторые из кода, который работает, но немного упрощен (класс тегов был уменьшен для удобства объяснения).
Ниже представлен класс Collection:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using Microsoft.SqlServer.Server;
namespace TagTableBuilder
{
public class TagCollection : List<Tag>, IEnumerable<SqlDataRecord>
{
IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator()
{
var sdr = new SqlDataRecord(
new SqlMetaData("Tag", SqlDbType.NVarChar)
);
foreach (Tag t in this)
{
sdr.SetSqlString(0, t.tagName);
yield return sdr;
}
}
}
public class Tag
{
public string tagName { get; set; }
}
}
Они называются следующим образом:
//Create instance of collection
TagCollection tags = new TagCollection();
//Create instance of object
Tag _tag = new Tag();
foreach (string t in tagList)
{
//Add value to class propety
_tag.tagName = t;
//Add class to collection, this is where all previously added rows are overwritten
tags.Add(_tag);
}
Ответы
Ответ 1
Вы используете тот же экземпляр объекта Tag
внутри цикла, поэтому каждое обновление для tagName относится к той же ссылке. Переместите объявление внутри цикла, чтобы получить новый объект на каждом проходе цикла:
foreach (string t in tagList)
{
Tag _tag = new Tag();
//Add value to class propety
_tag.tagName = t;
//Add class to collection, this is where all previously added rows are overwritten
tags.Add(_tag);
}
Также обратите внимание, что я обновил последнюю строку, чтобы добавить _tag
вместо mTag
, поскольку я не вижу этого в любом месте.
Ответ 2
В цикле, где вы добавляете теги в коллекцию, вы используете один и тот же экземпляр объекта Tag. По сути, вы устанавливаете имя тега для первого значения в tagList и добавляете его в коллекцию, затем вы меняете это же имя тега на второе значение в tagList и добавляете его снова в коллекцию.
Ваша коллекция тегов содержит несколько ссылок на один и тот же объект Tag! Мгновую активацию _tag внутри цикла for каждый раз перед установкой имени тега и добавлением его в коллекцию.