Переместить значение свойства элемента в списке к следующему элементу в этом списке

У меня есть два объекта, скажем Amount, NewAmount, оба имеют свойства ниже

public class Amount
{
    public Int64 Id { get; set; }
    public Int64 Amt1 { get; set; }
    public Int64 Amt2 { get; set; }
} 
public class NewAmountDo
{
   public Int64 newAmt { get; set; }
}

У меня есть список Amount с некоторыми значениями в нем и NewAmount Object с одним значением

List<Amount> amountListObject = new List<Amount>();
Amount amount = new Amount();
Amount amount1 = new Amount();
Amount amount2 = new Amount();
Amount amount3 = new Amount();
NewAmountDo newAmountDo = new NewAmountDo();
newAmountDo.newAmt = 50;
amount.Id = 1;
amount.Amt1 = 10;
amount.Amt2 = 100;
amountListObject.Add(amount);
amount1.Id = 2;
amount1.Amt1 = 20;
amount1.Amt2 = 200;
amountListObject.Add(amount1);
amount2.Id = 0;
amount2.Amt1 = 30;
amount2.Amt2 = 300;
amountListObject.Add(amount2);
amount3.Id = 0;
amount3.Amt1 = 40;
amount3.Amt2 = 400;
amountListObject.Add(amount3);

Console.WriteLine("Input ");
exising = amountListObject;

List<Amount> intermediate = new List<Amount>();
Amount newamount = new Amount();
intermediate.AddRange(amountListObject);
intermediate.Add(newamount);

Я пытаюсь добавить значение в свойстве newAmt в NewAmount Object к свойству Amt1 totalListObject и опустить значение Amt1 до значения Amt1 следующего элемента списка. Но я получаю значение первого Amt1 во всех Amt1 в списке. ниже приведен код, который я пробовал

for (int i = 0; i < intermediate.Count; i++)
{
    if (i == 0)
    {
       intermediate[i].Amt1 = newAmountDo.newAmt;
    }
    else
    {
       intermediate[i].Amt1 = exising[i - 1].Amt1;
    }
}

Следующее является входом:

Id : 1 , Amt1 : 10 , Amt2 : 100
Id : 2,  Amt1 : 20 , Amt2 : 200
Id : 0 , Amt1 : 30 , Amt2 : 300
Id : 0 , Amt1 : 40 , Amt2 : 400

Ниже приведен результат, который я получаю

Id : 1 , Amt1 : 50 , Amt2 : 100 
Id : 2 , Amt1 : 50 , Amt2 : 200
Id : 0 , Amt1 : 50 , Amt2 : 300
Id : 0 , Amt1 : 50 , Amt2 : 400
Id : 0 , Amt1 : 50 , Amt2 : 0

Ожидаемый результат:

Id : 1 , Amt1 : 50 , Amt2 : 100
Id : 2 , Amt1 : 10 , Amt2 : 200
Id : 0 , Amt1 : 20 , Amt2 : 300
Id : 0 , Amt1 : 30 , Amt2 : 400
Id : 0 , Amt1 : 40, Amt2 : 0

Есть ли способ добиться этого?

2 ответа

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

Я вижу 3 решения вашей проблемы:

  1. Используйте структуру вместо класса для вашего типа Amount. Это приведет к копированию значений вместо эталонной копии, поэтому у вас не будет одинакового экземпляра в двух списках, и у вас не будет никаких конфликтов.

  2. Если вам действительно нужно, чтобы ваш тип был классом, вы можете создать конструктор копирования и скопировать ваши элементы в промежуточный список следующим образом:

    intermediate.AddRange(amountListObject.Select(o => new Amount(o)));
    

    Таким образом, вы по-прежнему будете иметь ссылки в своих списках, но каждая ссылка будет указывать на отдельный экземпляр вашего типа Amount, следовательно, никаких конфликтов.

  3. Если вы хотите избежать какой-либо копии объектов, вам нужно будет изменить свой код, чтобы использовать промежуточное значение в вашем foreach, чтобы сохранить то, что было в предыдущей сумме, следующим образом:

    Int64 previous;
    for (int i = 0; i < intermediate.Count; i++)
    {
        if (i == 0)
        {
            previous = intermediate[i].Amt1;
            intermediate[i].Amt1 = newAmountDo.newAmt;
        }
        else
        {
            Int64 temp = intermediate[i].Amt1;
            intermediate[i].Amt1 = previous;
            previous = temp;
        }
    }
    

Сначала объявите конструктор для определенного класса, это поможет с инициализацией и улучшит читабельность кода.

public class Amount
    {
        public Int64 Id { get; set; }
        public Int64 Amt1 { get; set; }
        public Int64 Amt2 { get; set; }

        public Amount(Int64 Id, Int64 Amt1, Int64 Amt2)
        {
            this.Id = Id;
            this.Amt1 = Amt1;
            this.Amt2 = Amt2;
        }
    }
    public class NewAmountDo
    {
        public Int64 newAmt { get; set; }

        public NewAmountDo(Int64 newAmt)
        {
            this.newAmt = newAmt;
        }
    }

Теперь инициализация будет намного чище:

List<Amount> amountListObject = new List<Amount>();

Amount amount = new Amount(1,10,100);
Amount amount1 = new Amount(2,20,200);
Amount amount2 = new Amount(0,30,300);
Amount amount3 = new Amount(0,40,400);
NewAmountDo newAmount = new NewAmountDo(50);
amountListObject = new List<Amount>() { amount, amount1, amount2, amount3 };

Теперь исправлена ​​проблема:

Int64 shiftedAmt = 0;
        for (int i = 0; i < amountListObject.Count; i++)
        {                
            /* First element in the list */
            if (i == 0)
            {
                /* save the amt1 property value for shifting */
                shiftedAmt = amountListObject[i].Amt1;
                /* Switch to the new amount (if you need to add the new to the old just replace with +=) */
                amountListObject[i].Amt1 = newAmount.newAmt;
            }
            else
            {
                /* Shift the value */
                Int64 temp = amountListObject[i].Amt1;
                amountListObject[i].Amt1 = shiftedAmt;
                shiftedAmt = temp;
            }
        }
        /* Create new Amount object for the last shifted amt1 value */
        Amount _amount = new Amount(0, shiftedAmt, 0);
        amountListObject.Add(_amount);
Другие вопросы по тегам