Прежде всего, я хочу убедиться, что этот момент ясен: IntPtr - это просто целое число, размер которого совпадает с собственным указателем на архитектуре этого компьютера - это 64-разрядное целое число, например, в системах x64,Он не обязательно имеет семантику указателя, хотя, конечно, для кода взаимодействия характерно вставлять указатели в IntPtrs, чтобы безопасно их распределить.
Переходя к конкретному вопросу, давайте не будем обращать внимания на тот факт, что это IntPtr.Представьте, что это просто int, потому что это в основном то, что он есть:
public void Foo(ref int x) // x is an alias to another variable of type int.
{
int y = x; // y is a copy of the contents of x
y = 7; // The contents of y are no longer a copy of the contents of x
}
Изменение y никоим образом не меняет x;x является псевдонимом для другой переменной, а у y кратко есть копия содержимого этой переменной.Это никоим образом не является псевдонимом к той же переменной.
Как я могу превратить одну переменную в псевдоним другой переменной, поэтому, когда состояние одной переменной обновляется, связанная переменнаятоже обновился?В C ++ это не будет проблемой с указателем.
Сегодня в безопасном подмножестве вы можете сделать это только с помощью параметров "ref" и "out" для методов.Параметр ref становится псевдонимом данной переменной. Это единственный безопасный способ, которым вы можете напрямую превратить одну переменную в псевдоним для другой.
CLR также поддерживает локальные ссылки.Мы могли бы реализовать такую функцию, и на самом деле я создал ее на C #.В моем прототипе вы могли бы сказать:
public void Foo(ref int x) // x is an alias to another variable of type int.
{
ref int y = ref x; // y is now an alias to the same variable that x aliases!
y = 7; // changing y now changes x, and whatever x
// aliases, because those are all the same variable
}
Но мы не добавили эту функцию в C # и не планируем делать это в ближайшее время.Если у вас есть веские аргументы в пользу использования, я хотел бы услышать это.(ОБНОВЛЕНИЕ: функция была добавлена в C # 7.)
(CLR также разрешает типы возврата "ref". Однако CLR НЕ позволяет создавать псевдоним для переменной и затем сохранять этот псевдоним в поле.! Поле может иметь более длительный срок службы, чем связанная переменная, и разработчики CLR хотят избежать всего этого класса ошибок, которые преследуют C и C ++.)
Если вы знаете, что переменная закреплена в определенном местев памяти вы можете отключить систему безопасности и сделать указатель на эту переменную;тогда у вас есть совершенно обычный указатель, который вы можете использовать как в C ++.(То есть, если указатель ptr
ссылается на переменную, тогда *ptr
является псевдонимом этой переменной.)
unsafe public void Foo(int* x) // *x is an alias to a variable of type int.
{
int* y = x; // *y is now an alias to the same variable that *x aliases
*y = 7; // changing *y now changes *x, and whatever *x
// aliases, because those are all the same variable
}
В CLR нет ограничений на использование указателей;Вы можете хранить их в полях, если хотите.Однако если вы выключите систему безопасности, тогда вы несете ответственность за то, чтобы сборщик мусора (или любой другой диспетчер памяти, владеющий этим хранилищем - возможно, не управляемая память) не изменилсярасположение переменной с псевдонимом для времени жизни указателя .Не выключайте эту систему безопасности, если вы действительно не знаете, что делаете;эта система безопасности существует, чтобы защитить вас.