C#:指向多个整数的引用/指针数组

Fed*_*man 3 c# pointers integer reference short

我想在数组中引用一些短路.我假设我可以创建短裤,然后将它们添加到阵列中.所以......每次更改引用的对象时,都会反映在数组中,反之亦然.做一些试验使我确信它不是那么有效.事实上,看起来价值是转移而不是参考.

下面的代码创建了两个short,将这些作为对象添加到数组中,然后更改原始short.但是,当访问数组中假定的引用short时它没有改变,这使我相信它是一个与原始对象无关的全新对象.

        Console.WriteLine("Testing simple references:");
        short v1 = 1;
        short v2 = 2;
        object[] vs = new object[2];
        vs[0] = v1;
        vs[1] = v2;
        v1 = 1024;
        v2 = 512;
        Console.WriteLine(" v1: " + (short)vs[0]);
        Console.WriteLine(" v2: " + (short)vs[1]);
Run Code Online (Sandbox Code Playgroud)

我在这里误解了一些基本的东西,如果有人可以解释,我会很感激,并且可能会指出一个可以做我想做的解决方案.

Eri*_*ert 17

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);
Run Code Online (Sandbox Code Playgroud)

你去吧

现在,这将为您提供对short的引用访问,因为short实际存储在与该类的value属性关联的字段中.如果你那么说:

v2 = new ReferenceType<short>(3);
Console.WriteLine(vs[1].Value);
Run Code Online (Sandbox Code Playgroud)

你不会得到"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
Run Code Online (Sandbox Code Playgroud)

在这里,我们捕获数组对象,这些对象知道如何获取和设置v1和v2的当前值.

现在,如果您想要做的是直接为另一个变量创建一个别名,而没有这个对象,那么在C#中只有一种方法可以做到这一点:

void M(ref short x)
{
    x = 123;
}
...
short y = 1;
M(ref y);
Run Code Online (Sandbox Code Playgroud)

现在"x"和"y"是同一个变量的两个名字.但是,当别名变量是方法的形式参数时,"为另一个变量创建别名"的概念仅适用于C#.一般来说,没有办法做到这一点.

现在,理论上我们可以做你想要的事情.我们可以支持"ref locals":

short v1 = 1;
ref short rv1 = ref v1;
rv1 = 123;
Console.WriteLine(v1); // 123
Run Code Online (Sandbox Code Playgroud)

也就是说,rv1成为v1的别名.C#不支持这一点,但CLR确实如此,因此我们可以支持它.然而,CLR不支持发出"REF"元类型,或者存储参字段的阵列.所以从这个意义上讲,你无法做你想做的事.

C#支持一些特殊的"隐藏"功能,用于传递对象类似于对变量的引用,但权重比上面提到的"两个委托"引用更轻.但是,这些特殊功能仅适用于奇怪的互操作场景,我建议不要使用它们.(再说一次,你不能创建一个存储类型引用的数组.)我不认为我会在这个答案中更多地谈论这些功能; 你真的不想去那里,相信我.


Ada*_*ear 5

Short是一种值类型,但您尝试使其行为类似于引用类型.

您可以使用short属性创建一个类,然后使用该类的数组:

public class MyShort
{
    public short Value {get; set;}
}

public class SomeOtherClass
{
   public void SomeMethod()
   {
       MyShort[] array = new MyShort[2];
       array[0] = new MyShort {Value = 5};
       array[1] = new MyShort {Value = 2};

       array[0].Value = 3;
   }
}
Run Code Online (Sandbox Code Playgroud)

你可以做一些工作来使它更顺畅(比如将转换器从short你的包装器类中实现并返回).