C#引用数组

我怎么能这样做?

int v1 = 4; int v2 = 3; int v3 = 2; int v4 = 1; int [] vars = new int [] {ref v1, ref v2, ref v3, ref v4}; for (var i = 0; i < 4; i++) { ChangeVar (vars [i], i); } void ChangeVar (ref int thatVar, int newValue) { thatVar = newValue; } 

编辑:

我想这样做是因为这些变量是由其他类直接访问的。 比如v1可能是某物的宽度而v2可能是某物的高度。 我的一些类使用width变量来限制它必须从用户获得的输入的长度。 有些类使用height变量来做其他事情。 但我希望能够使用循环编辑这些变量,因为现在这是编辑过程的工作方式:

 int indexOfVarToChange = GetIndex (); switch (indexOfVarToChange) { case 0: int newValue = GetNewValue (); width = newValue; break; case 1: int newValue = GetNewValue (); height = newValue; break; } 

我必须手动重新分配变量,因为我不能在循环中使用这些变量的引用数组。 我有超过30个独特的变量,我必须这样做,这是一个痛苦。

我想回退计划是将所有这些变量移动到一个字典中,并拥有一个包含所有键的数组,并将每个键传递给编辑函数。

你不能。

您仍然可以在适当的位置编辑元素,但只能直接指定它们:

  vars[2] += 42; 

但我刚测试了这个作品:

 using System; public class Test { private static void assign(ref int i) { i = 42; } public static void Main() { var vars = new [] { 1,2,3,4 }; Console.WriteLine(vars[2]); assign(ref vars[2]); Console.WriteLine(vars[2]); } } 

看它现场http://ideone.com/fz36y

产量

 3 42 

更新:包装器

作为一项心理锻炼,我想出了这种生病和扭曲的机制,仍能得到你想要的东西(但是比简单地装箱所有的东西要花费更多):

 private class Wrap where T : struct { public T Value; public static implicit operator Wrap(T v) { return new Wrap { Value = v }; } public static implicit operator T(Wrap w) { return w.Value; } public override string ToString() { return Value.ToString(); } public override int GetHashCode() { return Value.GetHashCode(); } // TODO other delegating operators/overloads } 

现在, Wrap将大致表现为常规int(在比较,相等和运算符领域需要更多工作)。 您可以使用它来编写它,并让它以您想要的方式工作:

 private static void assign(ref int i) { i = 42; } public static void Main() { Wrap element = 7; var vars = new Wrap[] {1, 2, element, 3, 4}; Console.WriteLine(vars[2]); assign(ref vars[2].Value); Console.WriteLine(element); Console.ReadKey(); } 

输出:

 7 42 

现场观看:http://ideone.com/b0m7T

假设为了论证你确实需要做这样的事情,我认为在不使用不安全代码的情况下你能得到的最接近的是通过创建一个“持有”整数的小类Holder来改变你的代码以增加一个间接级别(或任何T)

 namespace ConsoleApplication33 { public static class Program { private static void Main() { var t1=new Holder(4); var t2=new Holder(3); var t3=new Holder(2); var t4=new Holder(1); var vars=new[] {t1, t2, t3, t4}; for(var i=0; i<4; i++) { ChangeVar(vars[i], i); } } static void ChangeVar(Holder thatVar, T newValue) { thatVar.Value=newValue; } public class Holder { public T Value { get; set; } public Holder(T value=default(T)) { Value=value; } } } } 

此类的InitializeAll方法通过使用Linq表达式和reflection来工作。 我认为这与您想要的代码具有相同的意图。 它将v1,v2,v3和v4分别初始化为0,1,2和3。

 using System; using System.Linq.Expressions; namespace ArrayOfReferences { public class InitializeMultipleVariables { int v1; int v2; int v3; int v4; public void InitializeAll() { Initialize( () => v1, () => v2, () => v3, () => v4); } public void Initialize(params Expression>[] intExpressions) { for (int i = 0; i < intExpressions.Length; i++) { var expr = intExpressions[i].Body as System.Linq.Expressions.MemberExpression; var fieldInfo = this.GetType().GetField(expr.Member.Name, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); fieldInfo.SetValue(this, i); } } } }