C # и сохранение ссылки на параметр метода

StackOverflow https://stackoverflow.com/questions/1633737

  •  06-07-2019
  •  | 
  •  

Вопрос

Для получения небольшой справочной информации, у меня есть приложение, которое выполняется в цикле, и с течением времени оно вызывает метод Tick .Есть куча классов, которые расширяют базовый класс, и у всех есть свои собственные методы tick, и они добавляются в цепочку зависимостей, так что, скажем, когда вызывается класс A и в его цепочке есть экземпляры B и C, вызывается B.Tick, за которым следует C.Tick и, наконец, A.Tick.

Итак, в псевдокоде мой класс выглядит примерно так:

public class A : Super
Super b;
Super c;
ArrayList one;
ArrayList two;

tick(){
    one.Add(b.LastValue);
    two.Add(c.LastValue);
            ... do something with one and two ...
}

A(){
    b = new B(some other array list);
    c = new C(ref one);
}

B работает нормально и всегда получает правильное значение.Проблема в том, что, я думаю, вы не можете сохранить ссылку на другую переменную в классе, поэтому, когда я делаю new C (ссылка one);и конструктор для C устанавливает переменную класса в единицу, позже, после обновления единицы в A, это похоже на то, что C больше не знает, что она все еще должна указывать на единицу (которая теперь обновлена) и просто пуста (как это изначально было внутри конструктора).Есть какие-нибудь идеи о том, как достичь того, что я хочу сделать, без необходимости использовать указатели C # и небезопасный код?Спасибо, надеюсь, это имеет смысл :)

Редактировать:По-видимому, люди не могут отвечать на вопросы с помощью запутанного псевдокода, который совершенно не связан с реальным вопросом, поэтому измененный распространяется на :

Правка 2:Класс С

...
ArrayList local;
...
C(ref ArrayList one){
    local = one;
}

Tick(){
   LastValue = local[0] + 5; //not actual formula, just shows trying to use a referenced variable 
}
Это было полезно?

Решение

С тех пор как one является ArrayList, вы можете Только передайте его в качестве ссылки.Теперь вы, по-видимому, передаете его как ссылку на ссылку на конструктор.Возможно, вам это не понадобится ref.

Но, пожалуйста, покажите более полное представление о том, чего вы пытаетесь достичь.

Редактировать:

После просмотра вашего класса C нет необходимости в ref. c будет совместно использовать экземпляр ArrayList, который вызывает A one.

Похоже, это сводится к общей проблеме referencetype / valuetype в .NET.Подводя итог:

  • экземпляры объектов не имеют имени и вообще не могут (физически) быть переданы в качестве параметра.
  • вы всегда получаете доступ к экземпляру через ссылку.В вашем коде, one (2 раза) , two, local все это ссылки на экземпляры Arraylist.
  • сами ссылки ведут себя как valuetypes, т. е. присвоение означает копирование.

Чтобы узнать больше о ссылочных типах / типах значений, выполните поиск "копировать семантику" и избегайте записей, начинающихся с "типы значений существуют в стеке".

Другие советы

Нет ничего, что могло бы помешать тебе сделать это.Хотя, хорошая это идея или нет, это другой вопрос.В общем, я бы рекомендовал стараться избегать изменения состояния между вызовами метода, если вы можете этого избежать.Конечно, ключевое выражение там - "если вы можете избежать этого".:-)

вы не можете сохранить ссылку на другую переменную в классе

Вы можете, люди делают это постоянно.Просто назначьте его (закрытому) полю.

поэтому, когда я делаю новый C (ссылка одна);[snip /] позже, после обновления одного из них в A, это похоже на то, что C больше не знает, что он все еще должен указывать на один

На самом деле, он знает это, но вы должны назначить one в поле участника.Присвоение объектам - это не что иное, как установка ссылки на объект.Изменяя объект, изменяйте их везде, где вы ему назначили:

class A
{
    public string Hello { get; set; }
}

class C
{
    private A myA;
    public C(A a) { myA = a; }
    public A GetMyA() { return myA; }
}

// somewhere else:
A someA = new A();
someA.Hello = "Hello World";
C someC = new C(someA);
someA.Hello = "Other World";
Console.WriteLine(someC.GetMyA().Hello);

// this will print "Other World" and not "Hello World" as you suggest

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

ППС:перечитывая ваш (отредактированный) код и все еще пытаясь выяснить, в чем проблема, кажется, ничто не мешает C в вашем коде от сохранения участника со ссылкой на A и зовущий a.Add очевидно, будет отражать переменную-член в c также.Действительно, нет необходимости в ref вот.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top