C#类型系统中有“值类型”和“引用类型”两种类型。
值类型是按值复制的;当您复制一个时,您会得到一个与原始对象无关的全新对象。
引用类型通过引用复制;当您复制一个时,您实际上是在复制对某个存储位置的引用。您会得到两个引用,它们都引用一个对象。
短裤是价值类型。
如果你想让一个 short 成为一个引用类型,那么你可以制作一个引用类型包装器:
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);
你去吧。
现在,这将为您提供对 short的引用访问权限,因为 short 实际上存储在与类的 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 locals”:
更新:我在这里讨论的“理论”特性已添加到 C# 7.0。
short v1 = 1;
ref short rv1 = ref v1;
rv1 = 123;
Console.WriteLine(v1); // 123
也就是说,rv1 成为 v1 的别名。C# 不支持这一点,但 CLR 支持,因此我们可以支持它。但是,CLR 不支持创建“ref”元素类型的数组或存储 ref 的字段。所以从这个意义上说,你不能做你想做的事。
C# 确实支持一些特殊的“隐藏”功能,用于传递类似于变量引用但比上面提到的“两个委托”引用更轻的对象。但是,这些特殊功能仅适用于奇怪的互操作场景,我建议不要使用它们。(同样,你不能创建一个存储类型引用的数组。)我认为我不会在这个答案中更多地讨论这些特性;你真的不想去那里,相信我。