Почему добавление нового значения в список перезаписывает предыдущие значения в списке

после нескольких учебных пособий и таких я смог успешно создать класс коллекции, который наследует функциональность, необходимую для создания DataTable, который может быть передан хранимой процедуре Sql Server в качестве параметра табличного значения. Кажется, все работает хорошо; я могу добавить все строки, и это выглядит красиво. Однако при ближайшем рассмотрении я замечаю, что при добавлении новой строки данные для всех предыдущих строк перезаписываются значением для новой строки. Так что если я есть строка со строковым значением "foo", и я добавляю вторую строку со значением" bar", вторая строка будет вставлена (делая DataTable с двумя строками), но обе строки будут иметь значение"bar". Кто-нибудь понимает, почему это так? Вот некоторые из кода, который работает, но был немного упрощен (класс тегов был уменьшен для удобства объяснения).

ниже приведен класс коллекции:

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);
}

2 ответов


вы используете тот же экземпляр 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 поскольку я не вижу, чтобы это определялось где-либо.


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

ваша коллекция тегов содержит несколько ссылок на один и тот же объект тега! Instantiate _tag внутри цикла for каждый раз перед установкой имени тега и добавила его в коллекцию.