在C#类型系统中有两种类型,即"值类型"和"引用类型"。
值类型是按值进行复制的;当你复制一个值类型时,你会得到一个与原始对象无关的全新对象。
引用类型是按引用进行复制的;当你复制一个引用类型时,实际上是复制了指向某个存储位置的引用。你会得到两个引用,它们都指向同一个对象。
Shorts 是值类型。
如果你想让 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);
现在你可以通过引用访问the short,因为短语实际上存储在与类的值属性相关联的字段中。如果您接下来说:
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);
Console.WriteLine(v2);
这里我们将对象捕获到数组中,这些对象知道如何获取和设置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)
也就是说,rv1成为v1的别名。C#不支持这个功能,但CLR支持,因此我们可以支持它。然而,CLR不支持创建“ref”元素类型的数组或存储引用的字段。因此,在这个意义上,你不能做你想要的事情。
C#支持一些特殊的“隐藏”功能,用于传递像变量引用一样的对象,但比上面提到的“两个委托”引用更轻量级。然而,这些特殊功能仅用于奇怪的互操作场景,我建议不要使用它们。(而且,你不能创建存储类型引用的数组。)我不认为我会在这个答案中进一步讨论这些功能;相信我,你真的不想去那里。
where T : struct
。虽然不是必须的,但更符合类型预期实现的概念。 - Joel Coehoorn