Хранение ссылки на объект в C#

Я задавался вопросом, как можно было сохранить ссылку на объект в .NET.

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

class Test
{
    private /*reference to*/ Object a;
    public Test(ref int a)
    {
        this.a = a;
        this.a = ((int)this.a) + 1;
    }
    public Object getA() { return this.a; }
}
/*
 * ...
 */
static void Main(string[] args)
{
    int a;
    a=3;
    Test t = new Test(ref a);
    Console.WriteLine(a);
    Console.WriteLine(t.getA());
    Console.ReadKey();
}

Произвести следующий вывод:

4
4

Идеально, я хотел бы сделать это, не пишущий класс обертки вокруг целого числа.

Другими словами, я думаю, что хочу указатели в .NET.

5
задан John Saunders 29 August 2010 в 03:45
поделиться

2 ответа

Вы не можете хранить ссылки на переменные в .NET, точка. Вы можете хранить ссылки на объекты , но не ссылки на переменные .

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

Теперь, даже если бы вы могли это сделать, описываемая вами операция небезопасна по другой причине. У вас есть (очень неудачно названная) переменная поля «a» типа «ссылка на объектную переменную» и (очень неудачно и запутанно названную) локальную переменную «a» типа «ссылка на переменную типа int». Даже если бы вы могли сохранить ссылку на переменную, не имеет смысла хранить ссылку на переменную типа int в чем-то типа «ссылка на переменную объекта», потому что эти два типа логически несовместимы.Операции, которые вы можете выполнять с ними, различны; в ссылку на объектную переменную может быть записана строка; ссылка на переменную типа int не может.

Возможно, я неправильно понимаю, но разве переменная, такая как указанное выше целое число, не будет помещена в объект, который затем может быть сохранен в качестве ссылки?

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

Да, упаковка превращает тип значения, например int, в ссылочный тип, например object. Это АБСОЛЮТНО НИЧЕГО не имеет отношения к ссылкам на переменные .

Когда вы делаете ссылку на переменную, вы создаете псевдоним для этой переменной. Когда вы говорите

void M(ref int y) { y = 123; }
...
int x = 0;
M(ref x);

, вы говорите: «x и y - два разных имени для одной и той же переменной».

Теперь, если вы хотите представить понятие «Я захватил переменную и хочу иметь возможность читать и записывать ее», тогда используйте делегаты:

class Ref<T>
{
    private Func<T> getter;
    private Action<T> setter;
    public Ref(Func<T> getter, Action<T> setter)
    {
        this.getter = getter;
        this.setter = setter;
    }
    public T Value
    {
        get { return getter(); }
        set { setter(value); }
    }
}
...
int abc = 123;
var refabc = new Ref<int>(()=>abc, x=>{abc=x;});
... now you can pass around refabc, store it in a field, and so on
refabc.Value = 456;
Console.WriteLine(abc); // 456
Console.WriteLine(refabc.Value); // 456

Имеет смысл?

{{1 }}
36
ответ дан 18 December 2019 в 05:15
поделиться

В C # нет концепции ссылочной переменной, аналогичной C ++ int & a . Есть обходные пути. Один из них - использовать замыкания:

class Test
{
    private Func<int> get_a;
    private Action<int> set_a;
    public Test(Func<int> get_a, Action<int> set_a)
    {
        this.get_a = get_a;
        this.set_a = set_a;
        this.set_a(this.get_a() + 1);
    }
    public Object getA() { return this.get_a(); }
}
/*
 * ...
 */
static void Main(string[] args)
{
    int a;
    a=3;
    Test t = new Test(() => a, n => { a = n; });
    Console.WriteLine(a);
    Console.WriteLine(t.getA());
    Console.ReadKey();
}

Я не перед VS, поэтому, пожалуйста, извините за любые досадные оплошности.

10
ответ дан 18 December 2019 в 05:15
поделиться