C#类型系统中有“值类型”和“引用类型”两种类型。
值类型是按值复制的;当您复制一个时,您会得到一个与原始对象无关的全新对象。
引用类型是通过引用复制的;当您复制一个时,您实际上是在复制对某个存储位置的引用。你会得到两个引用,它们都引用一个对象。
short 是值类型。
如果你想让一个 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# 确实支持一些特殊的“隐藏”功能来传递对象,这些对象的作用类似于对变量的引用,但比上面提到的“两个委托”引用更轻。但是,这些特殊功能仅适用于奇怪的互操作场景,我建议不要使用它们。 (同样,你不能创建一个存储类型引用的数组。)我认为我不会在这个答案中更多地讨论这些特性;你真的不想去那里,相信我。