Обновить дважды?ссылаясь на него в массиве - PullRequest
0 голосов
/ 20 октября 2018

у меня есть массив double?и я хочу обновить (установить) некоторые их значения.Однако, похоже, я не могу этого сделать.Я попытался сделать это напрямую, затем после некоторого исследования попробовал следующее, что также не обновляет исходный объект (в данном случае t2).Чего мне не хватает?Как я могу обновить базовые объекты, содержащиеся в массиве?

using System;

public class Program
{
    public static void tst(ref double? input, int mult)
    {
        Console.WriteLine(input);
        input = input * mult;
        Console.WriteLine(input);
    }
    public static void Main()
    {
        double? t1 = 1.1;
        double? t2 = 2.1;
        double? t3 = 3.1;
        double?[] ta = { t1, t2, t3 };
        // change value of t2
        tst(ref ta[1], 33);

        Console.WriteLine(t1);
        Console.WriteLine(t2); // I want this to be 69.3, but it’s still 2.1
        Console.WriteLine(t3);
    }
}

Ответы [ 3 ]

0 голосов
/ 20 октября 2018

Вы должны вызвать функцию tst как для ta [2], так и для ta [3] перед печатью Console.WriteLine

tst(ref ta[1], 33);
tst(ref ta[2], 33);
tst(ref ta[3], 33);

Console.WriteLine(ta[1]);
Console.WriteLine(ta[2]);
Console.WriteLine(ta[3]);

Console.WriteLine должно быть напечатано ta [i] ,потому что это значение указано в функции tst

0 голосов
/ 20 октября 2018

Причина в том, что, как было объяснено, массив, который вы имеете, является копией значения переменной, а не копией ее расположения в памяти.

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

  • Чтобы получить адрес, мы можем использовать &

  • Чтобы получить значение снова, мы можем использовать префикс *

  • Введите наши указатели, которые мы можем использовать type*

  • (IntPtr)(double*), просто чтобы мы могли отобразить адрес

Код

public unsafe static void tst(double* input, int multi)
{  
   Console.WriteLine("Make sure everything looks fine");
   Console.WriteLine($"Ptr: {(IntPtr)input}, Value: {*input}");

   // overwrite the location its pointing to
   *input *=  multi;

   Console.WriteLine($"Ptr: {(IntPtr)input}, Value: {*input}");    
}

private unsafe static void Main(string[] args)
{
   //Some numbers
   double t1 = 10;
   double t2 = 20;
   double t3 = 30;

   Console.WriteLine("Locations and values");
   Console.WriteLine($"Ptr: {(IntPtr)(double*)&t1}, Value: {t1}");
   Console.WriteLine($"Ptr: {(IntPtr)(double*)&t2}, Value: {t2}");
   Console.WriteLine($"Ptr: {(IntPtr)(double*)&t3}, Value: {t3}");

   // create an array that pointers to the memory location of my awesome numbers
   double*[] ta = { &t1, &t2, &t3 };

   // pass in the array an
   tst(ta[1], 324);
   Console.WriteLine("Double check the results");
   Console.WriteLine($"Ptr: {(IntPtr)(double*)&t1}, Value: {t1}");
   Console.WriteLine($"Ptr: {(IntPtr)(double*)&t2}, Value: {t2}");
   Console.WriteLine($"Ptr: {(IntPtr)(double*)&t3}, Value: {t3}");

}

Выход

Locations and values
Ptr: 5239124, Value: 10
Ptr: 5239116, Value: 20
Ptr: 5239108, Value: 30
Make sure everything looks fine
Ptr: 5239116, Value: 20
Ptr: 5239116, Value: 6480
Double check the results
Ptr: 5239124, Value: 10
Ptr: 5239116, Value: 6480
Ptr: 5239108, Value: 30

Дополнительные ресурсы

Обновление

Вы можете использовать индексатор

Хорошо, контекст в том, что у меня есть класс, который (среди прочего) содержит 12 double?свойства, представляющие месяцы года.Некоторая бизнес-логика определяет во время выполнения, какие из них должны быть обновлены, на основе входящего массива из 12 значений.Поэтому я надеялся использовать массив для управления этой реализацией, чтобы обновить их значения, а не 12 отдельных блоков для проверки и обновления условий.-

public class SomeClass
{
   public int P1 { get; set; }
   public int P2 { get; set; }
   public int P3 { get; set; }
   public int P4 { get; set; }
   public int P5 { get; set; }

   public int this[int i]
   {
      get {
         switch (i)
         {
            case 0: return P1;
            case 1: return P2;
            case 2: return P3;
            case 4: return P5;
         }
      }
      set
      {
         switch (i)
         {
            case 0: P1 = value;  break;
            case 1: P2 = value; break;
            case 2: P3 = value;  break;
            case 4: P4 = value; break;
         }
      }
   }
}

...

SomeClass[2] // access like an array
0 голосов
/ 20 октября 2018

Эта строка:

double?[] ta = { t1, t2, t3 };

ta - это новый массив типа double, использующий значения t1, t2, t3 (не их ссылки).и ta[1] не совпадает с t2, а просто имеет то же значение.таким образом, передача ta[1] через ref изменит значение ta[1], но не значение t2 (то есть только его значение было скопировано в ta).так что если вы посмотрите на ta[1] значение, оно должно быть изменено на 69,3

...