Сохранение ссылки на интервал

Вот очень упрощенная версия того, что я пытаюсь сделать

static void Main(string[] args)
{
    int test = 0;
    int test2 = 0;
    Test A = new Test(ref test);
    Test B = new Test(ref test);
    Test C = new Test(ref test2);
    A.write(); //Writes 1 should write 1
    B.write(); //Writes 1 should write 2
    C.write(); //Writes 1 should write 1
    Console.ReadLine();
}
class Test
{
    int _a;
    public Test(ref int a)
    {
        _a = a; //I loose the reference here
    }
    public void write()
    {
        var b = System.Threading.Interlocked.Increment(ref _a);
        Console.WriteLine(b);
    }
}

В моем реальном коде у меня есть интервал, который будет увеличен многими потоками однако, где потоки названный, не будет легко передать его параметр, который указывает на него на интервал (В реальном коде это происходит внутри a IEnumerator). Таким образом, требование является ссылкой, должен быть сделан в конструкторе. Также не все потоки будут указывать на тот же единственный основной интервал, таким образом, я не смогу использовать глобальный статический интервал также. Я знаю, что могу просто упаковать интервал в классе и раздать класс, но я хотел знать - ли это корректный способ сделать что-то вроде этого?

То, что я думаю, могло быть корректным путем:

static void Main(string[] args)
{
    Holder holder = new Holder(0);
    Holder holder2 = new Holder(0);
    Test A = new Test(holder);
    Test B = new Test(holder);
    Test C = new Test(holder2);
    A.write(); //Writes 1 should write 1
    B.write(); //Writes 2 should write 2
    C.write(); //Writes 1 should write 1
    Console.ReadLine();
}
class Holder
{
    public Holder(int i)
    {
        num = i;
    }
    public int num;
}
class Test
{
    Holder _holder;
    public Test(Holder holder)
    {
        _holder = holder;
    }
    public void write()
    {
        var b = System.Threading.Interlocked.Increment(ref _holder.num);
        Console.WriteLine(b);
    }
}

Существует ли лучший путь, чем это?

5
задан Bhargav Rao 30 April 2019 в 04:06
поделиться

3 ответа

По сути, ответ - да, вам нужен класс.

Не существует концепции «ссылки на int», которую можно было бы сохранить как поле. В C # это ограничено параметрами.

И хотя существует небезопасный способ (указатель на int, int * ), сложности работы с GC в этом сценарии делают его непрактичным и неэффективным.

Итак, ваш второй пример выглядит нормально.

5
ответ дан 14 December 2019 в 01:02
поделиться

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

Ваш подход к превращению переменной в поле класса вполне подходит. Альтернативный способ сделать то же самое - создать делегаты getter и setter для переменной. Если делегаты замкнуты на внешнюю локальную переменную, то эта внешняя локальная будет поднята в поле, так что ее время жизни будет больше, чем у делегатов.

3
ответ дан 14 December 2019 в 01:02
поделиться

Невозможно сохранить ссылку как поле.

Вам нужно сохранить int в классе.

1
ответ дан 14 December 2019 в 01:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: