В системе типов C # существует два типа типов: «типы значений» и «ссылочные типы».
Типы значений копируются по значению; когда вы копируете один, вы получаете совершенно новый объект, который не имеет ничего общего с оригиналом.
Типы ссылок копируются по ссылке; когда вы копируете один, вы фактически копируете ссылку на какое-то место хранения. Вы получаете две ссылки, которые обе ссылаются на один объект.
Шорты являются типами значений.
Если вы хотите, чтобы шорт был ссылочным типом, вы можете создать оболочку ссылочного типа:
class ReferenceType<T> where T : struct
{
public T Value { get; set }
public ReferenceType(T value) { this.Value = value; }
}
var v1 = new ReferenceType<short>(1);
var v2 = new ReferenceType<short>(2);
var vs = new ReferenceType<short>[2] { v1, v2 };
v1.Value = 1024;
v2.Value = 512;
Console.WriteLine(vs[0].Value);
Console.WriteLine(vs[1].Value);
И вот, пожалуйста.
Теперь это даст вам справочный доступ к короткому значению , поскольку короткое замыкание фактически хранится в поле, связанном со свойством значения класса. Если вы тогда скажете:
v2 = new ReferenceType<short>(3);
Console.WriteLine(vs[1].Value);
вы не получите «3» - v2 теперь ссылается на объект, отличный от vs [1]. Если то, что вы действительно хотите захватить, является ссылкой на переменную , тогда вы хотите использовать замыкание .
class ReferenceToVariable<T>
{
private Func<T> getter;
private Action<T> setter;
public ReferenceToVariable(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value { get { return getter(); } set { setter(value); } }
}
...
short v1 = 1;
short v2 = 2;
var vs = new []
{
new ReferenceToVariable<short>(()=>v1, x=>{v1=x;}),
new ReferenceToVariable<short>(()=>v2, x=>{v2=x;})
};
v1 = 123;
vs[1].Value = 456;
Console.WriteLine(vs[0].Value); // 123
Console.WriteLine(v2); // 456
Здесь мы собираем в массив объекты, которые знают, как получить и установить текущие значения v1 и v2.
Теперь, если вы хотите сделать псевдоним для другой переменной напрямую , без использования этого объекта, тогда есть только один способ сделать это в C # :
void M(ref short x)
{
x = 123;
}
...
short y = 1;
M(ref y);
Теперь "x" и "y" - это два имени для одной и той же переменной. Однако понятие «сделать псевдоним другой переменной» работает только в C #, когда переменная псевдонимов является формальным параметром метода. В общем, сделать это невозможно.
Теперь мы можем теоретически сделать что-то вроде того, что вы хотите. Мы могли бы поддержать "ref localals":
short v1 = 1;
ref short rv1 = ref v1;
rv1 = 123;
Console.WriteLine(v1); // 123
То есть rv1 становится псевдонимом для v1. C # не поддерживает это, но CLR поддерживает, и поэтому мы могли бы это поддержать. Однако CLR не поддерживает создание массивов типа ref или полей, в которых хранятся ссылки. Так что в этом смысле вы не можете делать то, что хотите.
C # поддерживает некоторые специальные «скрытые» функции для передачи объектов, которые действуют как ссылки на переменные, но имеют меньший вес, чем ссылка «два делегата», упомянутая выше. Однако эти специальные функции предназначены только для странных сценариев взаимодействия, и я рекомендую против них. (И опять же, вы не можете создать массив, в котором хранятся типизированные ссылки.) Не думаю, что я расскажу об этих функциях подробнее в этом ответе; ты действительно не хочешь туда идти, поверь мне.